

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/bear.jpg">
  <link rel="icon" href="/img/bear.jpg">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Wahoyu">
  <meta name="keywords" content="">
  
    <meta name="description" content="本项目是基于SSM的图书管理系统，使用Thymeleaf作为前端模板，使用SpringSecurity进行用户登录权限相关的管理操作。">
<meta property="og:type" content="article">
<meta property="og:title" content="基于SSM+Security的图书管理系统">
<meta property="og:url" content="http://example.com/2022/07/26/BookManagerSSM/index.html">
<meta property="og:site_name" content="哆啦是个梦-A Coding Bear">
<meta property="og:description" content="本项目是基于SSM的图书管理系统，使用Thymeleaf作为前端模板，使用SpringSecurity进行用户登录权限相关的管理操作。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://example.com/image/22.07.26/1.jpg">
<meta property="article:published_time" content="2022-07-26T08:40:00.000Z">
<meta property="article:modified_time" content="2022-08-29T06:45:56.191Z">
<meta property="article:author" content="Wahoyu">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="实战">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://example.com/image/22.07.26/1.jpg">
  
  
    <meta name="referrer" content="no-referrer-when-downgrade">
  
  
  <title>基于SSM+Security的图书管理系统 - 哆啦是个梦-A Coding Bear</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  



  
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/shubiao.css#.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.9.0","typing":{"enable":true,"typeSpeed":90,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":3},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>

  
<meta name="generator" content="Hexo 6.2.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 30vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>哆啦是个梦</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="基于SSM+Security的图书管理系统"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        Wahoyu
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-07-26 16:40" pubdate>
          2022年7月26日 下午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          44k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          371 分钟
        
      </span>
    

    
    
      
        <span id="busuanzi_container_page_pv" style="display: none">
          <i class="iconfont icon-eye" aria-hidden="true"></i>
          <span id="busuanzi_value_page_pv"></span> 次
        </span>
        
      
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar category-bar" style="margin-right: -1rem">
    





<div class="category-list">
  
  
    
    
    
    <div class="category row nomargin-x">
      <a class="category-item 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="开发"
        id="heading-3ff3c3e26a68112c11c3e80f2a26896e" role="tab" data-toggle="collapse" href="#collapse-3ff3c3e26a68112c11c3e80f2a26896e"
        aria-expanded="true"
      >
        开发
        <span class="list-group-count">(9)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-3ff3c3e26a68112c11c3e80f2a26896e"
           role="tabpanel" aria-labelledby="heading-3ff3c3e26a68112c11c3e80f2a26896e">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/2022/06/05/SQL%E5%9F%BA%E7%A1%80%E8%AF%AD%E5%8F%A5%E6%97%A5%E5%B8%B8%E7%BB%83%E4%B9%A0/" title="SQL语句练习"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">SQL语句练习</span>
        </a>
      
    
      
      
        <a href="/2022/06/19/%E5%85%B3%E4%BA%8E%E5%8F%8D%E5%B0%84%E4%B8%8E%E6%B3%A8%E8%A7%A3%E7%9A%84%E7%90%86%E8%A7%A3%E4%B8%8E%E6%80%BB%E7%BB%93/" title="关于反射与注解的理解与总结"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">关于反射与注解的理解与总结</span>
        </a>
      
    
      
      
        <a href="/2022/07/06/JavaWeb/" title="基于Java Web的图书管理系统"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">基于Java Web的图书管理系统</span>
        </a>
      
    
      
      
        <a href="/2022/06/27/%E5%9F%BA%E4%BA%8EMybatis-JUL-Lombok-Maven%E7%9A%84%E5%9B%BE%E4%B9%A6%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%EF%BC%88%E5%B8%A6%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%EF%BC%89/" title="基于Mybatis的图书管理系统"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">基于Mybatis的图书管理系统</span>
        </a>
      
    
      
      
        <a href="/2022/07/26/BookManagerSSM/" title="基于SSM+Security的图书管理系统"
           class="list-group-item list-group-item-action
           active">
          <span class="category-post">基于SSM+Security的图书管理系统</span>
        </a>
      
    
      
      
        <a href="/2022/06/10/%E7%AE%80%E5%8D%95%E7%AE%97%E6%B3%95%EF%BC%88Java%E5%AE%9E%E7%8E%B0%EF%BC%89/" title="排序与搜索算法（Java实现）"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">排序与搜索算法（Java实现）</span>
        </a>
      
    
      
      
        <a href="/2022/06/08/Java%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%AE%80%E5%8D%95%E5%AE%9E%E7%8E%B0/" title="数据结构实现（Java）"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">数据结构实现（Java）</span>
        </a>
      
    
      
      
        <a href="/2022/08/30/%E6%97%A5%E5%BF%97%E8%BF%9B%E5%8C%96%EF%BC%9AAOP+%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0%E6%97%A5%E5%BF%97%E8%BE%93%E5%87%BA/" title="日志进化：AOP+自定义注解实现日志输出"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">日志进化：AOP+自定义注解实现日志输出</span>
        </a>
      
    
      
      
        <a href="/2022/06/03/%E8%A7%A3%E5%86%B3Linux%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E6%AF%8F%E6%AC%A1%E8%A6%81source-etc-profile%E9%97%AE%E9%A2%98/" title="解决Linux环境变量每次要source /etc/profile问题"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">解决Linux环境变量每次要source /etc/profile问题</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
</div>


  </aside>


    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">基于SSM+Security的图书管理系统</h1>
            
            <div class="markdown-body">
              
              <p>本项目是基于SSM的图书管理系统，使用Thymeleaf作为前端模板，使用SpringSecurity进行用户登录权限相关的管理操作。</p>
<span id="more"></span>

<h3 id="项目成果展示"><a href="#项目成果展示" class="headerlink" title="项目成果展示"></a>项目成果展示</h3><p><img src="/image/22.07.26/shifan1.jpg" srcset="/img/loading.gif" lazyload></p>
<p><img src="/image/22.07.26/shifan2.jpg" srcset="/img/loading.gif" lazyload></p>
<h3 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h3><ul>
<li><p><input checked="" disabled="" type="checkbox"> 
自定义登录登出</p>
</li>
<li><p><input checked="" disabled="" type="checkbox"> 
针对不同权限规划不同页面</p>
</li>
<li><p><input checked="" disabled="" type="checkbox"> 
学生的注册</p>
</li>
<li><p><input checked="" disabled="" type="checkbox"> 
管理员的功能：增删书籍、查看全部借阅信息</p>
</li>
<li><p><input checked="" disabled="" type="checkbox"> 
学生的功能：借阅归还书籍、查看自己的借阅信息</p>
</li>
</ul>
<h1 id="开发环境测试"><a href="#开发环境测试" class="headerlink" title="开发环境测试"></a>开发环境测试</h1><p>我们依然使用之前的前端模板来搭建图书管理系统项目。</p>
<h3 id="导入依赖"><a href="#导入依赖" class="headerlink" title="导入依赖"></a>导入依赖</h3><p>导入以下依赖：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br><span class="hljs-comment">&lt;!--Thymeleaf视图解析器--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.thymeleaf<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>thymeleaf-spring5<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.0.12.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-comment">&lt;!--  Spring框架依赖  --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.security<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-security-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.5.3<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.security<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-security-config<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.5.3<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-webmvc<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.3.14<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br><span class="hljs-comment">&lt;!--  持久层框架依赖  --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>mysql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mysql-connector-java<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>8.0.27<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis-spring<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.0.6<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.5.7<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-jdbc<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>5.3.14<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.zaxxer<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>HikariCP<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.4.5<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br><span class="hljs-comment">&lt;!--  其他工具框架依赖：Lombok、Slf4j  --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.18.22<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>slf4j-jdk14<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.7.32<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br><span class="hljs-comment">&lt;!--  ServletAPI  --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>javax.servlet<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>javax.servlet-api<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.0.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>provided<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br><span class="hljs-comment">&lt;!--  JUnit依赖  --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.junit.jupiter<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit-jupiter-api<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>$&#123;junit.version&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.junit.jupiter<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit-jupiter-engine<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>$&#123;junit.version&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="删除无用文件夹"><a href="#删除无用文件夹" class="headerlink" title="删除无用文件夹"></a>删除无用文件夹</h3><p>删除JSP，初始化servlet等</p>
<p><img src="/image/22.07.26/image_qnhCBdqacn.png" srcset="/img/loading.gif" lazyload></p>
<h3 id="创建初始化包"><a href="#创建初始化包" class="headerlink" title="创建初始化包"></a>创建初始化包</h3><p>接着创建Initializer（初始化包，专门来初始化的包）来配置Web应用程序</p>
<p><img src="/image/22.07.26/image_Ys3dnwa9sI.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="MVC初始化器"><a href="#MVC初始化器" class="headerlink" title="MVC初始化器"></a>MVC初始化器</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MvcInitializer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AbstractAnnotationConfigDispatcherServletInitializer</span> &#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> Class&lt;?&gt;[] getRootConfigClasses() &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Class</span>[]&#123;RootConfiguration.class&#125;;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> Class&lt;?&gt;[] getServletConfigClasses() &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Class</span>[]&#123;MvcConfiguration.class&#125;;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> String[] getServletMappings() &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">String</span>[]&#123;<span class="hljs-string">&quot;/&quot;</span>&#125;;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>然后就是将两个没有写的初始化器进行完善</p>
<p><img src="/image/22.07.26/image_lnfheZjmB-.png" srcset="/img/loading.gif" lazyload></p>
<h3 id="配置类"><a href="#配置类" class="headerlink" title="配置类"></a>配置类</h3><p>创建配置类</p>
<h4 id="Mvc配置类"><a href="#Mvc配置类" class="headerlink" title="Mvc配置类"></a>Mvc配置类</h4><p>mvc扫描Controller</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@ComponentScan(&quot;book.manager.controller&quot;)</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@EnableWebMvc</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MvcConfiguration</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">WebMvcConfigurer</span> &#123;<br><br>    <span class="hljs-comment">//我们需要使用ThymeleafViewResolver作为视图解析器，并解析我们的HTML页面</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> ThymeleafViewResolver <span class="hljs-title function_">thymeleafViewResolver</span><span class="hljs-params">(<span class="hljs-meta">@Autowired</span> SpringTemplateEngine springTemplateEngine)</span>&#123;<br>        <span class="hljs-type">ThymeleafViewResolver</span> <span class="hljs-variable">resolver</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThymeleafViewResolver</span>();<br>        resolver.setOrder(<span class="hljs-number">1</span>);<br>        resolver.setCharacterEncoding(<span class="hljs-string">&quot;UTF-8&quot;</span>);<br>        resolver.setTemplateEngine(springTemplateEngine);<br>        <span class="hljs-keyword">return</span> resolver;<br>    &#125;<br><br>    <span class="hljs-comment">//配置模板解析器</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> SpringResourceTemplateResolver <span class="hljs-title function_">templateResolver</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">SpringResourceTemplateResolver</span> <span class="hljs-variable">resolver</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SpringResourceTemplateResolver</span>();<br>        resolver.setSuffix(<span class="hljs-string">&quot;.html&quot;</span>);<br>        resolver.setPrefix(<span class="hljs-string">&quot;/WEB-INF/template/&quot;</span>);<br>        <span class="hljs-keyword">return</span> resolver;<br>    &#125;<br><br>    <span class="hljs-comment">//配置模板引擎Bean</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> SpringTemplateEngine <span class="hljs-title function_">springTemplateEngine</span><span class="hljs-params">(<span class="hljs-meta">@Autowired</span> ITemplateResolver resolver)</span>&#123;<br>        <span class="hljs-type">SpringTemplateEngine</span> <span class="hljs-variable">engine</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SpringTemplateEngine</span>();<br>        engine.setTemplateResolver(resolver);<br>        <span class="hljs-keyword">return</span> engine;<br>    &#125;<br><br>    <span class="hljs-comment">//开启静态资源处理</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configureDefaultServletHandling</span><span class="hljs-params">(DefaultServletHandlerConfigurer configurer)</span> &#123;<br>        configurer.enable();<br>    &#125;<br><br>    <span class="hljs-comment">//静态资源路径配置</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">addResourceHandlers</span><span class="hljs-params">(ResourceHandlerRegistry registry)</span> &#123;<br>        registry.addResourceHandler(<span class="hljs-string">&quot;/static/**&quot;</span>).addResourceLocations(<span class="hljs-string">&quot;/WEB-INF/static/&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Root配置类"><a href="#Root配置类" class="headerlink" title="Root配置类"></a>Root配置类</h4><p>扫描Service</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@ComponentScan(&#123;</span><br><span class="hljs-meta">        &quot;book.manager.service&quot;</span><br><span class="hljs-meta">&#125;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">RootConfiguration</span> &#123;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="启动测试"><a href="#启动测试" class="headerlink" title="启动测试"></a>启动测试</h3><h4 id="Controller"><a href="#Controller" class="headerlink" title="Controller"></a>Controller</h4><p>最后创建一个专用于响应页面的PageController即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 专用于处理页面响应的控制器</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Controller</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">PageController</span> &#123;<br><br>    <span class="hljs-meta">@RequestMapping(&quot;/index&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">login</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;index&quot;</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="配置前端相关文件夹"><a href="#配置前端相关文件夹" class="headerlink" title="配置前端相关文件夹"></a>配置前端相关文件夹</h4><p>将static直接放进WEB-INF文件夹中，再创建一个template文件夹专门用于放前端模板</p>
<p>接着我们需要将前端页面放到对应的文件夹中，然后开启服务器并通过浏览器，成功访问。</p>
<p><img src="/image/22.07.26/image_9ka_BERLcV.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="网站前缀"><a href="#网站前缀" class="headerlink" title="网站前缀"></a>网站前缀</h4><p>修改Tomcat服务器部署URL和应用程序上下文</p>
<p><img src="/image/22.07.26/image_hYPArvtsxz.png" srcset="/img/loading.gif" lazyload></p>
<p><img src="/image/22.07.26/image_YPXlMFvBCb.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="访问测试"><a href="#访问测试" class="headerlink" title="访问测试"></a>访问测试</h4><p>在默认地址后面输入index</p>
<p>访问成功！</p>
<p><img src="/image/22.07.26/image_BeDKTOyywR.png" srcset="/img/loading.gif" lazyload></p>
<h1 id="配置Security环境"><a href="#配置Security环境" class="headerlink" title="配置Security环境"></a>配置Security环境</h1><h4 id="Security初始化器"><a href="#Security初始化器" class="headerlink" title="Security初始化器"></a>Security初始化器</h4><p>接着我们需要配置SpringSecurity，与Mvc一样，需要一个<em><strong>初始化器</strong></em>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SecurityInitializer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AbstractSecurityWebApplicationInitializer</span> &#123;<br>    <span class="hljs-comment">//不用重写任何内容</span><br>    <span class="hljs-comment">//这里实际上会自动注册一个Filter，SpringSecurity底层就是依靠N个过滤器实现的，我们之后再探讨</span><br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Security配置类"><a href="#Security配置类" class="headerlink" title="Security配置类"></a>Security配置类</h4><p>接着我们需要再创建一个配置类用于配置SpringSecurity：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@EnableWebSecurity</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SecurityConfiguration</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">WebSecurityConfigurerAdapter</span> &#123;<br>    <span class="hljs-comment">//继承WebSecurityConfigurerAdapter，之后会进行配置</span><br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="配置MVC初始化器"><a href="#配置MVC初始化器" class="headerlink" title="配置MVC初始化器"></a>配置MVC初始化器</h4><p>接着在mvc容器中添加此配置文件即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> Class&lt;?&gt;[] getRootConfigClasses() &#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Class</span>[]&#123;RootConfiguration.class, SecurityConfiguration.class&#125;;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>这样，SpringSecurity的配置就完成了，我们再次运行项目，会发现无法进入的我们的页面中，无论我们访问哪个页面，都会进入到SpringSecurity为我们提供的一个默认登录页面，之后我们会讲解如何进行配置。</p>
<p>至此，项目环境搭建完成。</p>
<p>Security自动出现了一个登陆页面</p>
<p><img src="/image/22.07.26/image_0Vdhg55s_4.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="添加Thymeleaf对Security的支持"><a href="#添加Thymeleaf对Security的支持" class="headerlink" title="添加Thymeleaf对Security的支持"></a>添加Thymeleaf对Security的支持</h4><p>开始之前我们需要先配置一下Thymeleaf的SpringSecurity扩展，它针对SpringSecurity提供了更多额外的解析：</p>
<p>导入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.thymeleaf.extras<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>thymeleaf-extras-springsecurity5<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.0.4.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>MVC配置类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//配置模板引擎Bean</span><br><span class="hljs-meta">@Bean</span><br><span class="hljs-keyword">public</span> SpringTemplateEngine <span class="hljs-title function_">springTemplateEngine</span><span class="hljs-params">(<span class="hljs-meta">@Autowired</span> ITemplateResolver resolver)</span>&#123;<br>    <span class="hljs-type">SpringTemplateEngine</span> <span class="hljs-variable">engine</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SpringTemplateEngine</span>();<br>    engine.setTemplateResolver(resolver);<br>    engine.addDialect(<span class="hljs-keyword">new</span> <span class="hljs-title class_">SpringSecurityDialect</span>());   <span class="hljs-comment">//添加针对于SpringSecurity的方言</span><br>    <span class="hljs-keyword">return</span> engine;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="/image/22.07.26/image_nOaHvTkzsW.png" srcset="/img/loading.gif" lazyload></p>
<p>前端头部</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">&quot;http://www.thymeleaf.org&quot;</span></span><br><span class="hljs-tag">      <span class="hljs-attr">xmlns:sec</span>=<span class="hljs-string">&quot;http://www.thymeleaf.org/extras/spring-security&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h1 id="登录登出记住我"><a href="#登录登出记住我" class="headerlink" title="登录登出记住我"></a>登录登出记住我</h1><h2 id="登录功能实现"><a href="#登录功能实现" class="headerlink" title="登录功能实现"></a>登录功能实现</h2><p>我们知道前端输入的密码会被Security翻译成密文，这就导致我们数据库中存储的必须是经过翻译的密文，否则经过转换之后密码不能与之对应。</p>
<p>像是这种向数据库中查询的操作，因为数据库中已经有了数据，我们可以先写mapper进行查询，然后从Service中进行直接调用以及逻辑处理（说是Service实际上相当于ServiceImpl，注意此时应给配置RootConfiguration对mapper和service进行扫描，应该是Security有与之对应的Service，所以负责相对应的Impl就可以了）</p>
<p>再将Service传入到相应的应用部分（Security或者Controller）</p>
<p>我们这次是将Service传入SecurityConfiguration进行逻辑处理。</p>
<h3 id="配置数据库层"><a href="#配置数据库层" class="headerlink" title="配置数据库层"></a>配置数据库层</h3><p>前面我们已经实现了直接认证的方式，那么如何将其连接到数据库，通过查询数据库中的内容来进行用户登录呢？</p>
<h4 id="Test翻译密码为密文"><a href="#Test翻译密码为密文" class="headerlink" title="Test翻译密码为密文"></a>Test翻译密码为密文</h4><p>首先我们需要将加密后的密码添加到数据库中作为用户密码(注意不同的项目的翻译出来的密文不同)：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MainTest</span> &#123;<br><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">test</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">BCryptPasswordEncoder</span> <span class="hljs-variable">encoder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>();<br>        System.out.println(encoder.encode(<span class="hljs-string">&quot;123456&quot;</span>));<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>这里编写一个测试来完成。</p>
<h4 id="查询密码Mapper"><a href="#查询密码Mapper" class="headerlink" title="查询密码Mapper"></a>查询密码Mapper</h4><p>别忘了在配置类中进行扫描，将其注册为Bean，接着我们需要编写一个Mapper用于和数据库交互：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Mapper</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">UserMapper</span> &#123;<br><br>    <span class="hljs-meta">@Select(&quot;select password from users where name = #&#123;username&#125;&quot;)</span><br>    String <span class="hljs-title function_">getPasswordByUsername</span><span class="hljs-params">(String username)</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="根容器配置"><a href="#根容器配置" class="headerlink" title="根容器配置"></a>根容器配置</h4><p>根容器用来扫描mapper和service，配置一下Mybatis和数据源：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@ComponentScans(&#123;</span><br><span class="hljs-meta">        @ComponentScan(&quot;book.manager.service&quot;)</span><br><span class="hljs-meta">&#125;)</span><br><span class="hljs-meta">@MapperScan(&quot;book.manager.mapper&quot;)</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">RootConfiguration</span> &#123;<br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> DataSource <span class="hljs-title function_">dataSource</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">HikariDataSource</span> <span class="hljs-variable">dataSource</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HikariDataSource</span>();<br>        dataSource.setJdbcUrl(<span class="hljs-string">&quot;jdbc:mysql://localhost:3306/book_manage_ssm&quot;</span>);<br>        dataSource.setDriverClassName(<span class="hljs-string">&quot;com.mysql.cj.jdbc.Driver&quot;</span>);<br>        dataSource.setUsername(<span class="hljs-string">&quot;root&quot;</span>);<br>        dataSource.setPassword(<span class="hljs-string">&quot;123456&quot;</span>);<br>        <span class="hljs-keyword">return</span> dataSource;<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> SqlSessionFactoryBean <span class="hljs-title function_">sqlSessionFactoryBean</span><span class="hljs-params">(<span class="hljs-meta">@Autowired</span> DataSource dataSource)</span>&#123;<br>        <span class="hljs-type">SqlSessionFactoryBean</span> <span class="hljs-variable">bean</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SqlSessionFactoryBean</span>();<br>        bean.setDataSource(dataSource);<br>        <span class="hljs-keyword">return</span> bean;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>这样，登陆就会从数据库中进行查询。</p>
<h3 id="配置Service和Security逻辑"><a href="#配置Service和Security逻辑" class="headerlink" title="配置Service和Security逻辑"></a>配置Service和Security逻辑</h3><h4 id="比对密码Service"><a href="#比对密码Service" class="headerlink" title="比对密码Service"></a>比对密码Service</h4><p>然后我们需要创建一个Service实现，实现的是UserDetailsService，它支持我们自己返回一个UserDetails对象，我们只需直接返回一个包含数据库中的用户名、密码等信息的UserDetails即可，SpringSecurity会自动进行比对。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Service</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserAuthService</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">UserDetailsService</span> &#123;<br><br>    <span class="hljs-meta">@Resource</span><br>    UserMapper mapper;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> UserDetails <span class="hljs-title function_">loadUserByUsername</span><span class="hljs-params">(String s)</span> <span class="hljs-keyword">throws</span> UsernameNotFoundException &#123;<br>        <span class="hljs-type">String</span> <span class="hljs-variable">password</span> <span class="hljs-operator">=</span> mapper.getPasswordByUsername(s);  <span class="hljs-comment">//从数据库根据用户名获取密码</span><br>        <span class="hljs-keyword">if</span>(password == <span class="hljs-literal">null</span>)<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernameNotFoundException</span>(<span class="hljs-string">&quot;登录失败，用户名或密码错误！&quot;</span>);<br>        <span class="hljs-keyword">return</span> User   <span class="hljs-comment">//这里需要返回UserDetails，SpringSecurity会根据给定的信息进行比对</span><br>                .withUsername(s)<br>                .password(password)   <span class="hljs-comment">//直接从数据库取的密码</span><br>                .roles(<span class="hljs-string">&quot;user&quot;</span>)   <span class="hljs-comment">//用户角色</span><br>                .build();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Security配置"><a href="#Security配置" class="headerlink" title="Security配置"></a>Security配置</h4><p>最后再重新修改一下Security配置：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configure</span><span class="hljs-params">(AuthenticationManagerBuilder auth)</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>    auth<br>      .userDetailsService(service)   <span class="hljs-comment">//使用自定义的Service实现类进行验证</span><br>      .passwordEncoder(<span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>());   <span class="hljs-comment">//依然使用BCryptPasswordEncoder</span><br>&#125;<br></code></pre></td></tr></table></figure>

<h2 id="登录页面自定义"><a href="#登录页面自定义" class="headerlink" title="登录页面自定义"></a>登录页面自定义</h2><p>首先我们关闭csrf，这个隐藏的框的作用是携带Token进入每一个网页，没携带的会自动被拦截。关闭了csrf之后可以不用继续在网页中携带Token,不过我们只是为了方便，在实际开发的时候不能本末倒置。</p>
<p>由于使用了SpringSecurity，我们所有的与登录以及权限相关的比如登录页，首页，登录跳转请求，等等都是在SecurityConfiguration中进行配置</p>
<p>在前端更换了Security对应的变量名，方法名，请求名之后，在Security中进行继续配置即可，虽然Security取代了部分的Controller的重定向跳转功能但是具体的网址对应的页面还是要Controller进行编写。</p>
<h3 id="前端配置"><a href="#前端配置" class="headerlink" title="前端配置"></a>前端配置</h3><h4 id="添加Login-html页面"><a href="#添加Login-html页面" class="headerlink" title="添加Login.html页面"></a>添加Login.html页面</h4><p><img src="/image/22.07.26/image_wb9DhJz_In.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="前端更改表单提交action"><a href="#前端更改表单提交action" class="headerlink" title="前端更改表单提交action"></a>前端更改表单提交action</h4><p>页面跳转链接我们都是通过Controller进行跳转，前端的按钮我们要在前端的action和method进行命名。</p>
<p><img src="/image/22.07.26/image_y5P5s38E1H.png" srcset="/img/loading.gif" lazyload></p>
<h3 id="后端替换默认界面"><a href="#后端替换默认界面" class="headerlink" title="后端替换默认界面"></a>后端替换默认界面</h3><h4 id="SecurityConfiguration"><a href="#SecurityConfiguration" class="headerlink" title="SecurityConfiguration"></a>SecurityConfiguration</h4><p>接着我们就可以将我们自己的页面替换掉默认的页面了，我们需要重写另一个方法来实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>    http<br>            .authorizeRequests()   <span class="hljs-comment">//首先需要配置哪些请求会被拦截，哪些请求必须具有什么角色才能访问</span><br>            .antMatchers(<span class="hljs-string">&quot;/static/**&quot;</span>).permitAll()    <span class="hljs-comment">//静态资源，使用permitAll来运行任何人访问（注意一定要放在前面）</span><br>            .antMatchers(<span class="hljs-string">&quot;/**&quot;</span>).hasRole(<span class="hljs-string">&quot;user&quot;</span>)     <span class="hljs-comment">//所有请求必须登陆并且是user角色才可以访问（不包含上面的静态资源）</span><br>&#125;<br></code></pre></td></tr></table></figure>

<p>首先我们需要配置拦截规则，也就是当用户未登录时，哪些路径可以访问，哪些路径不可以访问，如果不可以访问，那么会被自动重定向到登陆页面。</p>
<p>接着我们需要配置表单登陆和登录页面：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java">.and()<br>.formLogin()       <span class="hljs-comment">//配置Form表单登陆</span><br>.loginPage(<span class="hljs-string">&quot;/login&quot;</span>)       <span class="hljs-comment">//登陆页面地址（GET）</span><br>.loginProcessingUrl(<span class="hljs-string">&quot;/doLogin&quot;</span>)    <span class="hljs-comment">//form表单提交地址（POST）</span><br>.defaultSuccessUrl(<span class="hljs-string">&quot;/index&quot;</span>，<span class="hljs-literal">true</span>)    <span class="hljs-comment">//登陆成功后跳转的页面，也可以通过Handler实现高度自定义</span><br>.permitAll()    <span class="hljs-comment">//登陆页面也需要允许所有人访问</span><br></code></pre></td></tr></table></figure>

<h3 id="关闭csrf"><a href="#关闭csrf" class="headerlink" title="关闭csrf"></a>关闭csrf</h3><p>由于我们在学习的过程中暂时用不到CSFR防护，因此可以将其关闭，这样直接使用get请求也可以退出登陆，并且登陆请求中无需再携带Token了，推荐关闭，因为不关闭后面可能会因为没考虑CSRF防护而遇到一连串的问题：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">.and()<br>.csrf().disable();<br></code></pre></td></tr></table></figure>

<p>这样就可以直接关闭此功能了，但是注意，这样将会导致您的Web网站存在安全漏洞。（这里为了之后省事，就关闭保护了，但是一定要记得在不关闭的情况下需要携带Token访问）</p>
<h4 id="Controller-1"><a href="#Controller-1" class="headerlink" title="Controller"></a>Controller</h4><p>需要配置登陆页面的地址和登陆请求发送的地址，这里登陆页面填写为<code>/login</code>，登陆请求地址为<code>/doLogin</code>，登陆页面需要我们自己去编写Controller来实现，登陆请求提交处理由SpringSecurity提供，只需要写路径就可以了。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/login&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">login</span><span class="hljs-params">()</span>&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;login&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h2 id="登出功能实现"><a href="#登出功能实现" class="headerlink" title="登出功能实现"></a>登出功能实现</h2><p>退出的逻辑比登录要简单一点，Security自动对退出操作进行了身份删除，我们只需要简单的对两个地方进行修改</p>
<p>①前端的按钮名称以及方法名称</p>
<p>②SecurityConfiguration的logout的请求地址名称和退出后返回的网址</p>
<h4 id="SecurityConfiguration-1"><a href="#SecurityConfiguration-1" class="headerlink" title="SecurityConfiguration"></a>SecurityConfiguration</h4><p>配置好后，我们还需要配置一下退出登陆操作：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java">.and()<br>.logout()<br>.logoutUrl(<span class="hljs-string">&quot;/logout&quot;</span>)    <span class="hljs-comment">//退出登陆的请求地址</span><br>.logoutSuccessUrl(<span class="hljs-string">&quot;/login&quot;</span>);    <span class="hljs-comment">//退出后重定向的地址</span><br></code></pre></td></tr></table></figure>

<h4 id="前端配置-1"><a href="#前端配置-1" class="headerlink" title="前端配置"></a>前端配置</h4><p>注意这里的退出登陆请求也必须是POST请求方式</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">&quot;logout&quot;</span> <span class="hljs-attr">method</span>=<span class="hljs-string">&quot;post&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>退出登陆<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>登陆成功后，点击退出登陆按钮，就可以成功退出并回到登陆界面了。</p>
<h2 id="记住我"><a href="#记住我" class="headerlink" title="记住我"></a>记住我</h2><p>由于之前的Cookie存储用户名和密码存在一定的危险，我们选择使用Security的两种记住我的形式。</p>
<p>①将Token存在内存中，不过重启服务器会导致Token失效，重启浏览器倒是没有什么关系。</p>
<p>②将Token存在数据库中，重启服务器时Security相关的配置会消失</p>
<h4 id="配置SecurityConfiguration"><a href="#配置SecurityConfiguration" class="headerlink" title="配置SecurityConfiguration"></a>配置SecurityConfiguration</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java">.and()<br>.rememberMe()   <span class="hljs-comment">//开启记住我功能</span><br>.rememberMeParameter(<span class="hljs-string">&quot;remember&quot;</span>)  <span class="hljs-comment">//登陆请求表单中需要携带的参数，如果携带，那么本次登陆会被记住</span><br>.tokenRepository(<span class="hljs-keyword">new</span> <span class="hljs-title class_">InMemoryTokenRepositoryImpl</span>())  <span class="hljs-comment">//这里使用的是直接在内存中保存的TokenRepository实现</span><br>  <span class="hljs-comment">//TokenRepository有很多种实现，InMemoryTokenRepositoryImpl直接基于Map实现的，缺点就是占内存、服务器重启后记住我功能将失效</span><br>  <span class="hljs-comment">//后面我们还会讲解如何使用数据库来持久化保存Token信息</span><br></code></pre></td></tr></table></figure>

<h4 id="前端修改"><a href="#前端修改" class="headerlink" title="前端修改"></a>前端修改</h4><p>接着我们需要在前端修改一下记住我勾选框的名称，将名称修改与上面一致，如果上面没有配置名称，那么默认使用”remember”作为名称：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;checkbox&quot;</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;remember&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-checkbox&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>现在我们启动服务器，在登陆时勾选记住我勾选框，观察Cookie的变化。</p>
<p><img src="/image/22.07.26/image_drMElTj5vn.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="重启服务器失效"><a href="#重启服务器失效" class="headerlink" title="重启服务器失效"></a>重启服务器失效</h4><p><em><strong>将Token存在内存中会导致服务器重启之后就消失</strong></em></p>
<p>虽然现在已经可以实现记住我功能了，但是还有一定的缺陷，如果服务器重新启动（因为Token信息全部存在HashMap中，也就是存在内存中），那么所有记录的Token信息将全部丢失，这时即使浏览器携带了之前的Token也无法恢复之前登陆的身份。</p>
<h1 id="学生注册"><a href="#学生注册" class="headerlink" title="学生注册"></a>学生注册</h1><h4 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h4><p>首先我们找到一个注册页面对其进行内容相关的规划，进行数据库以及网页前端的统一。输入框的name。</p>
<p><em><strong>显示上</strong></em>：</p>
<p>我们设置一个前端链接get请求（实际上前端对method不需要有具体的限制）。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">&quot;register&quot;</span>&gt;</span>注册用户<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>通过前端的get请求传到Controller</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//注册页面</span><br><span class="hljs-meta">@RequestMapping(&quot;/register&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">register</span><span class="hljs-params">()</span>&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;register&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>这时候我们发现进入页面的时候不能进入，会重定向到主页，原因是我们在设置Security的时候没有对Registerye页面进行放行。（注意要在拦截的前面）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//register页面，匀速所有人进行访问</span><br>.antMatchers(<span class="hljs-string">&quot;/register&quot;</span>).permitAll()<br></code></pre></td></tr></table></figure>

<p><em><strong>数据上</strong></em>：</p>
<p>在数据流程上，我们将数据输入前端，以表单的方式将数据传到Controller中</p>
<p>Controller将数据提取出来放到变量里面，调用Service中的方法，以存取了数据的变量为参数传入进去。</p>
<p>实际上Service也只是调用了mapper的方法，继续将变量的值继续传入mapper定义的接口方法中。</p>
<p>在Mapper中定义的传入的参数名与数据库中的变量名并没有什么必然的联系，因为可以使用@Param注解将变量的值传入sql语句中。</p>
<p><em><strong>设计上</strong></em>：</p>
<p>我们先设计前端对应的名字到Controller的post方法中，将变量值与之对应。</p>
<h3 id="简单框架设计"><a href="#简单框架设计" class="headerlink" title="简单框架设计"></a>简单框架设计</h3><h4 id="重新设计数据库"><a href="#重新设计数据库" class="headerlink" title="重新设计数据库"></a>重新设计数据库</h4><p>我们重新设计数据库表主要是因为多了users这一张表，users关系着登陆权限和访问权限。</p>
<p>设置外键</p>
<p><img src="/image/22.07.26/image_KC3Dm6V9ZE.png" srcset="/img/loading.gif" lazyload></p>
<p>我们让student表中的uid字段引用users的id字段。那么此时student就是从表，子表，外键。users表就是主表，父表，主键。</p>
<p>--创建时：先创建主键，再创建外键 &amp;#x20;</p>
<p>--删除时：先删除外键，再删建主键</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_61122628/article/details/123763603">https://blog.csdn.net/qq_61122628/article/details/123763603</a></p>
<h4 id="前端配置-2"><a href="#前端配置-2" class="headerlink" title="前端配置"></a>前端配置</h4><p>输入框的name</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;name&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">&quot;姓名&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-input&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;sex&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">&quot;性别&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-input&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;grade&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">&quot;年级&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-input&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">&quot;密码&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-input&quot;</span>&gt;</span><br><br></code></pre></td></tr></table></figure>

<p>提交键使用button</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-auth-btn&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-btn ad-login-member&quot;</span>&gt;</span>注册<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>表单头使用doRegister连接，前面没有斜杠。注明请求方法</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">&quot;doRegister&quot;</span> <span class="hljs-attr">method</span>=<span class="hljs-string">&quot;post&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h4 id="Controller的post方法"><a href="#Controller的post方法" class="headerlink" title="Controller的post方法"></a>Controller的post方法</h4><p>注意Controller类上要写出@Controller</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//注册测试</span><br><span class="hljs-meta">@RequestMapping(value=&quot;/doRegister&quot; , method = RequestMethod.POST)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">register</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;username&quot;)</span> String username,</span><br><span class="hljs-params">                       <span class="hljs-meta">@RequestParam(&quot;sex&quot;)</span> String sex,</span><br><span class="hljs-params">                       <span class="hljs-meta">@RequestParam(&quot;grade&quot;)</span> String grade,</span><br><span class="hljs-params">                       <span class="hljs-meta">@RequestParam(&quot;password&quot;)</span> String password)</span>&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;login&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="前端传值到Controller测试"><a href="#前端传值到Controller测试" class="headerlink" title="前端传值到Controller测试"></a>前端传值到Controller测试</h3><blockquote>
<p>报错;至少有一个JAR被扫描用于TLD但尚未包含TLD。?</p>
<p>j解决：在设置catalina.properties中，将&#x2F;转换成 *.jar</p>
</blockquote>
<blockquote>
<p>报错：没有直接跳转到调试页面</p>
<p>解决：因为Security将doRegister这个Post方法挡住了！！！我们要对“&#x2F;doRegister”方法进行放行</p>
</blockquote>
<blockquote>
<p>报错：前端传入的值“男”乱码</p>
<p>解决：在MvcInitializer中添加Filter</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//配置前端传值乱码Filter(无效，因为SpringSecurity的Filter自动前置)</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> Filter[] getServletFilters() &#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Filter</span>[]&#123;<span class="hljs-keyword">new</span> <span class="hljs-title class_">CharacterEncodingFilter</span>(<span class="hljs-string">&quot;utf-8&quot;</span>,<span class="hljs-literal">true</span>)&#125;;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>正常情况下这样配置是没有问题的。但是没有什么用，因为SpringSecurity会把自己的Filter放在最前面，我们自己写的被放在后面，数据来的时候已经就乱码了。</p>
<p>所以我们应该弄个前置方法，在里面设置Filter</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//配置前端传值乱码Filter(领先于Security的Filters)</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onStartup</span><span class="hljs-params">(ServletContext servletContext)</span> <span class="hljs-keyword">throws</span> ServletException &#123;<br>    servletContext.addFilter(<span class="hljs-string">&quot;characterEncodingFilter&quot;</span>,<span class="hljs-keyword">new</span> <span class="hljs-title class_">CharacterEncodingFilter</span>(<span class="hljs-string">&quot;UTF-8&quot;</span>,<span class="hljs-literal">true</span>))<br>            .addMappingForUrlPatterns(<span class="hljs-literal">null</span>,<span class="hljs-literal">false</span>,<span class="hljs-string">&quot;/*&quot;</span>);<br>    <span class="hljs-built_in">super</span>.onStartup(servletContext);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="/image/22.07.26/image_n3-buJRBrZ.png" srcset="/img/loading.gif" lazyload></p>
</blockquote>
<h3 id="配置后端代码"><a href="#配置后端代码" class="headerlink" title="配置后端代码"></a>配置后端代码</h3><h4 id="AuthService"><a href="#AuthService" class="headerlink" title="AuthService"></a>AuthService</h4><p>创建AuthService使用来专门负责与用户登录授权相关的Service操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">AuthService</span> &#123;<br>    <span class="hljs-type">boolean</span> <span class="hljs-title function_">register</span><span class="hljs-params">(String username,String sex,String grade,String password)</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Mapper"><a href="#Mapper" class="headerlink" title="Mapper"></a>Mapper</h4><p>新增了回写实体类的操作：我们在插入了用户信息表之后需要获取到uid，在后续插入学生表的时候需要用到。这时候我们选择的就是插入之后回写到实体类的一个操作（因为如果反过来进行查询的话，可能会出现重名不同uid的情况，就算进行时间上的排序也是比较麻烦）</p>
<p>我们的思路流程是先将信息插入user表中，然后通过回写实体类的机制将uid返回到实体类，我们在获取实体类之后将uid输入到student表中</p>
<p>mapper新增了@Option注解，会将信息对实体类有所反馈.</p>
<p>将传入的参数改成了实体类的对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Mapper</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">UserMapper</span> &#123;<br><br>    <span class="hljs-meta">@Select(&quot;select password from users where name = #&#123;username&#125;&quot;)</span><br>    AuthUser <span class="hljs-title function_">getPasswordByUsername</span><span class="hljs-params">(String username)</span>;<br><br>    <span class="hljs-comment">//注册时插入users</span><br>    <span class="hljs-comment">//options表示的是一层对应关系。true的意思是主键是自动生成的，keyColomn表示的数据库的主键，keyProperty表示的时对应的实体类中的键</span><br>    <span class="hljs-meta">@Options(useGeneratedKeys = true,keyColumn = &quot;id&quot;,keyProperty = &quot;id&quot;)</span><br>    <span class="hljs-meta">@Insert(&quot;insert into users(name,role,password) values(#&#123;username&#125;,#&#123;role&#125;,#&#123;password&#125;)&quot;)</span><br>    <span class="hljs-type">int</span> <span class="hljs-title function_">registerUser</span><span class="hljs-params">(AuthUser user)</span>;<br><br>    <span class="hljs-comment">//注册时插入student</span><br>    <span class="hljs-meta">@Insert(&quot;insert into student(uid,name,grade,sex) values(#&#123;uid&#125;,#&#123;name&#125;,#&#123;grade&#125;,#&#123;sex&#125;)&quot;)</span><br>    <span class="hljs-type">int</span> <span class="hljs-title function_">addStudentInfo</span><span class="hljs-params">(<span class="hljs-meta">@Param(&quot;uid&quot;)</span> <span class="hljs-type">int</span> uid,<span class="hljs-meta">@Param(&quot;name&quot;)</span> String name,<span class="hljs-meta">@Param(&quot;grade&quot;)</span> String grade,<span class="hljs-meta">@Param(&quot;sex&quot;)</span> String sex)</span>;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<h4 id="完善AuthServiceImpl"><a href="#完善AuthServiceImpl" class="headerlink" title="完善AuthServiceImpl"></a>完善AuthServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Service</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AuthServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">AuthService</span> &#123;<br><br>    <span class="hljs-meta">@Resource</span><br>    UserMapper mapper;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">register</span><span class="hljs-params">(String username, String sex, String grade, String password)</span> &#123;<br>        <span class="hljs-type">BCryptPasswordEncoder</span> <span class="hljs-variable">encoder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>();<br>        <span class="hljs-type">AuthUser</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">AuthUser</span>(<span class="hljs-number">0</span>,username,encoder.encode(password),<span class="hljs-string">&quot;user&quot;</span>);<br>        <span class="hljs-keyword">if</span>(mapper.registerUser(user)&lt;=<span class="hljs-number">0</span>)&#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;用户信息添加失败！&quot;</span>);<br>        &#125;<br>        <span class="hljs-keyword">if</span>(mapper.addStudentInfo(user.getId(),username,grade,sex)&lt;=<span class="hljs-number">0</span>)&#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;学生信息插入失败！&quot;</span>);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Controller关联Service"><a href="#Controller关联Service" class="headerlink" title="Controller关联Service"></a>Controller关联Service</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Controller</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AuthController</span> &#123;<br>    <span class="hljs-meta">@Resource</span><br>    AuthService service;<br><br>    <span class="hljs-comment">//注册测试</span><br>    <span class="hljs-meta">@RequestMapping(value=&quot;/doRegister&quot; , method = RequestMethod.POST)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">register</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;username&quot;)</span> String username,</span><br><span class="hljs-params">                           <span class="hljs-meta">@RequestParam(&quot;sex&quot;)</span> String sex,</span><br><span class="hljs-params">                           <span class="hljs-meta">@RequestParam(&quot;grade&quot;)</span> String grade,</span><br><span class="hljs-params">                           <span class="hljs-meta">@RequestParam(&quot;password&quot;)</span> String password)</span>&#123;<br>        service.register(username, sex, grade, password);<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;login&quot;</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="将注册的Service中的返回值改成void"><a href="#将注册的Service中的返回值改成void" class="headerlink" title="将注册的Service中的返回值改成void"></a>将注册的Service中的返回值改成void</h4><p>没必要写成boolean，因为我们直接抛出异常</p>
<blockquote>
<p>报错：Controller类找不到Service bean</p>
<p>原因：我们应该给Service的Impl实现类加上@Service接口，来让RootConfiguration找到他。</p>
</blockquote>
<blockquote>
<p>users表中出现了数据，但是数据没有加入到student中。</p>
<p>2.我们在ServiceImpl中进行插入学生的操作时，将学生的sex写成了password，导致传值失败</p>
</blockquote>
<p><img src="/image/22.07.26/image_TEwfWmq9I5.png" srcset="/img/loading.gif" lazyload></p>
<p>我们应该做一个事务，让他们要不就都插入，要不就都失败。</p>
<h3 id="student和users的事务操作"><a href="#student和users的事务操作" class="headerlink" title="student和users的事务操作"></a>student和users的事务操作</h3><p>我们将插入uesrs和student表的操作设置成一个事务，这样就能保证原子性。</p>
<p>在Spring阶段深入Mybatis框架中，使用Spring进行事务管理的具体方法是三步①给RootConfiguration配置类加上注解②给RootConfiguration加上一个事务支持的方法③将要执行的事务放在Service的一个方法中，在方法上打上注解</p>
<h4 id="RootConf设置"><a href="#RootConf设置" class="headerlink" title="RootConf设置"></a>RootConf设置</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@ComponentScans(&#123;</span><br><span class="hljs-meta">        @ComponentScan(&quot;book.manager.service&quot;)</span><br><span class="hljs-meta">&#125;)</span><br><span class="hljs-meta">@MapperScan(&quot;book.manager.mapper&quot;)</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-comment">//开启Spring事务</span><br><span class="hljs-meta">@EnableTransactionManagement</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">RootConfiguration</span> &#123;<br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> DataSource <span class="hljs-title function_">dataSource</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">HikariDataSource</span> <span class="hljs-variable">dataSource</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HikariDataSource</span>();<br>        dataSource.setJdbcUrl(<span class="hljs-string">&quot;jdbc:mysql://localhost:3306/book_manage_ssm&quot;</span>);<br>        dataSource.setDriverClassName(<span class="hljs-string">&quot;com.mysql.cj.jdbc.Driver&quot;</span>);<br>        dataSource.setUsername(<span class="hljs-string">&quot;root&quot;</span>);<br>        dataSource.setPassword(<span class="hljs-string">&quot;123456&quot;</span>);<br>        <span class="hljs-keyword">return</span> dataSource;<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> SqlSessionFactoryBean <span class="hljs-title function_">sqlSessionFactoryBean</span><span class="hljs-params">(<span class="hljs-meta">@Autowired</span> DataSource dataSource)</span>&#123;<br>        <span class="hljs-type">SqlSessionFactoryBean</span> <span class="hljs-variable">bean</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SqlSessionFactoryBean</span>();<br>        bean.setDataSource(dataSource);<br>        <span class="hljs-keyword">return</span> bean;<br>    &#125;<br><br>    <span class="hljs-comment">//开启事务管理</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> TransactionManager <span class="hljs-title function_">transactionManager</span><span class="hljs-params">(<span class="hljs-meta">@Autowired</span> DataSource dataSource)</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">DataSourceTransactionManager</span>(dataSource);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Service注解"><a href="#Service注解" class="headerlink" title="Service注解"></a>Service注解</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Resource</span><br>UserMapper mapper;<br><br><span class="hljs-meta">@Transactional</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">register</span><span class="hljs-params">(String username, String sex, String grade, String password)</span> &#123;<br>    <span class="hljs-type">BCryptPasswordEncoder</span> <span class="hljs-variable">encoder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>();<br>    <span class="hljs-type">AuthUser</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">AuthUser</span>(<span class="hljs-number">0</span>,username,encoder.encode(password),<span class="hljs-string">&quot;user&quot;</span>);<br>    <span class="hljs-keyword">if</span>(mapper.registerUser(user)&lt;=<span class="hljs-number">0</span>)&#123;<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;用户信息添加失败！&quot;</span>);<br>    &#125;<br>    <span class="hljs-keyword">if</span>(mapper.addStudentInfo(user.getId(),username,grade,sex)&lt;=<span class="hljs-number">0</span>)&#123;<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;学生信息插入失败！&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>关于test用户密码无效的问题</p>
<p>就算是相同的用户名和密码注册，生成的密码都是不同的，因为翻译的时候加了盐。所以不同的用户，相同的密码，密文不同也是很正常的事情。test换了个性别就可以正常登录了，应该是浏览器或则Security的奇怪缓存问题导致的。暂时没有更好的解决办法。</p>
<p>解决：其实是我们刚开始对数据进行字符串校验的时候，后来开始将字符串类型改成了AuthUser对象类型。在AuthUserService部分代码（String转换成AuthUser）没有进行修改。而且mapper语句也要继续修改成<code>select * </code>因为我们现在要进行搜索的是整个对象了</p>
<p>思路：查密码主要分为两个思路，一个是通过用户名查找密码，但是此时我们也需要获得role相关的信息，所以我们通过整个实体类对象进行查找比较方便。</p>
<p>我们在前端设置了doLogin之后直接创建一个AuthUserService，继承自Security的UserDetailsService类。因为是Security的自动识别，我们没有Controller，也不用对Service进行引用。只需要继承Security的类就行。</p>
<p>Service类引用mapper，mapper查询的是对应名字的用户的所有信息，方便我们后面将信息封装成一个对象。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Select(&quot;select * from users where name = #&#123;username&#125;&quot;)</span><br>AuthUser <span class="hljs-title function_">getPasswordByUsername</span><span class="hljs-params">(String username)</span>;<br></code></pre></td></tr></table></figure>

<p>在Service创建对象为mapper的,Security将前端输入信息和返回的对象进行信息比对。</p>
<p>Security将前端输入信息和返回的对象进行信息比对。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> UserDetails <span class="hljs-title function_">loadUserByUsername</span><span class="hljs-params">(String s)</span> <span class="hljs-keyword">throws</span> UsernameNotFoundException &#123;<br>        <span class="hljs-type">AuthUser</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> mapper.getPasswordByUsername(s);  <span class="hljs-comment">//从数据库根据用户名获取密码</span><br>        <span class="hljs-keyword">if</span>(user == <span class="hljs-literal">null</span>) &#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernameNotFoundException</span>(<span class="hljs-string">&quot;登录失败，用户名或密码错误！&quot;</span>);<br>        &#125;<br>        <span class="hljs-keyword">return</span> User   <span class="hljs-comment">//这里需要返回UserDetails，SpringSecurity会根据给定的信息进行比对</span><br>                .withUsername(user.getName())<br>                .password(user.getPassword())   <span class="hljs-comment">//直接从数据库取的密码</span><br>                .roles(user.getRole())   <span class="hljs-comment">//用户角色</span><br>                .build();<br>    &#125;<br></code></pre></td></tr></table></figure>
</blockquote>
<h4 id="User表中的名字设置不能重复"><a href="#User表中的名字设置不能重复" class="headerlink" title="User表中的名字设置不能重复"></a>User表中的名字设置不能重复</h4><p>由于如果出现了重复的字段，我们进行密码验证就会出现错误，所以我们要给name进行unique限制。由于name不是主键不能设置主键unique，所以我们要在索引中对name进行限制。</p>
<p><img src="/image/22.07.26/image_LS2BQEIQE_.png" srcset="/img/loading.gif" lazyload></p>
<h3 id="统一Security对“-x2F-api-x2F-auth”路径的放行"><a href="#统一Security对“-x2F-api-x2F-auth”路径的放行" class="headerlink" title="统一Security对“&#x2F;api&#x2F;auth”路径的放行"></a>统一Security对“&#x2F;api&#x2F;auth”路径的放行</h3><p>我们给AuthController加上了<code>/api/auth</code>前缀，然后在Security中对此路径进行放行。</p>
<p>在Security中对注册和登录和注册提交的POST请求进行了前缀放行</p>
<p>在前端对命令进行了修改注意前端的action前面不带斜杠，但是Security中的命令都是带斜杠</p>
<p>然后修改Controller中的重定向命令，因为我们在整个类上面加上了前缀，所以我们要对重定向写上完整的也买你返回路径。（注意重定向的写法）</p>
<h4 id="AuthController-重定向"><a href="#AuthController-重定向" class="headerlink" title="AuthController+重定向"></a>AuthController+重定向</h4><p>给页面加上了个名字前缀</p>
<p>注意重定向写法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Controller</span><br><span class="hljs-meta">@RequestMapping(&quot;/api/auth&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AuthController</span> &#123;<br>    <span class="hljs-meta">@Resource</span><br>    AuthService service;<br><br>    <span class="hljs-comment">//注册测试</span><br>    <span class="hljs-meta">@RequestMapping(value=&quot;/register&quot; , method = RequestMethod.POST)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">register</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;username&quot;)</span> String name,</span><br><span class="hljs-params">                           <span class="hljs-meta">@RequestParam(&quot;sex&quot;)</span> String sex,</span><br><span class="hljs-params">                           <span class="hljs-meta">@RequestParam(&quot;grade&quot;)</span> String grade,</span><br><span class="hljs-params">                           <span class="hljs-meta">@RequestParam(&quot;password&quot;)</span> String password)</span>&#123;<br>        service.register(name, sex, grade, password);<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;redirect:/login&quot;</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="SecurityConfiguration-2"><a href="#SecurityConfiguration-2" class="headerlink" title="SecurityConfiguration"></a>SecurityConfiguration</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java">http<br>    <span class="hljs-comment">//拦截放行</span><br>    .authorizeRequests()   <span class="hljs-comment">//首先需要配置哪些请求会被拦截，哪些请求必须具有什么角色才能访问</span><br>    .antMatchers(<span class="hljs-string">&quot;/static/**&quot;</span>,<span class="hljs-string">&quot;/register&quot;</span>,<span class="hljs-string">&quot;/login&quot;</span>,<span class="hljs-string">&quot;/api/auth/**&quot;</span>).permitAll()    <span class="hljs-comment">//静态资源，使用permitAll来运行任何人访问（注意一定要放在前面）</span><br>    .anyRequest().hasRole(<span class="hljs-string">&quot;user&quot;</span>)     <span class="hljs-comment">//所有请求必须登陆并且是user角色才可以访问（不包含上面的静态资源）</span><br><br>    <span class="hljs-comment">//自定义登陆页面</span><br>    .and()<br>    .formLogin()       <span class="hljs-comment">//配置Form表单登陆</span><br>    .loginPage(<span class="hljs-string">&quot;/login&quot;</span>)       <span class="hljs-comment">//登陆页面地址（GET）</span><br>    .loginProcessingUrl(<span class="hljs-string">&quot;/api/auth/login&quot;</span>)    <span class="hljs-comment">//form表单提交地址（POST）</span><br>    .defaultSuccessUrl(<span class="hljs-string">&quot;/index&quot;</span>,<span class="hljs-literal">true</span>)    <span class="hljs-comment">//登陆成功后跳转的页面，也可以通过Handler实现高度自定义</span><br>    .permitAll()    <span class="hljs-comment">//登陆页面也需要允许所有人访问</span><br><br>    <span class="hljs-comment">//退出</span><br>    .and()<br>    .logout()<br>    .logoutUrl(<span class="hljs-string">&quot;/api/auth/logout&quot;</span>)    <span class="hljs-comment">//退出登陆的请求地址</span><br>    .logoutSuccessUrl(<span class="hljs-string">&quot;/login&quot;</span>)    <span class="hljs-comment">//退出后重定向的地址</span><br></code></pre></td></tr></table></figure>

<h4 id="前端对应进行修改"><a href="#前端对应进行修改" class="headerlink" title="前端对应进行修改"></a>前端对应进行修改</h4><p>提交表单</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!--注册表单请求--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">&quot;api/auth/register&quot;</span> <span class="hljs-attr">method</span>=<span class="hljs-string">&quot;post&quot;</span>&gt;</span><br><span class="hljs-comment">&lt;!--登录表达请求--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">&quot;api/auth/login&quot;</span>    <span class="hljs-attr">method</span>=<span class="hljs-string">&quot;post&quot;</span>&gt;</span><br><span class="hljs-comment">&lt;!--退出按钮请求--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;api/auth/logout&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;fas fa-sign-out-alt&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span> logout<br><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br><br></code></pre></td></tr></table></figure>

<blockquote>
<p>在登陆时出现了奇怪的bug，就是使用中文用户名的时候，不能登录，显示bug。但是调试的时候却可以进行登录。然后在我清除浏览器缓存之后，maven-clean，重新构建Maven项目，RebuildProject之后，可以正常登陆了，暂时归结为缓存问题。</p>
</blockquote>
<h1 id="主页搭建"><a href="#主页搭建" class="headerlink" title="主页搭建"></a>主页搭建</h1><h2 id="主页总体框架搭建"><a href="#主页总体框架搭建" class="headerlink" title="主页总体框架搭建"></a>主页总体框架搭建</h2><h4 id="中文乱码再次优化"><a href="#中文乱码再次优化" class="headerlink" title="中文乱码再次优化"></a>中文乱码再次优化</h4><p>我们发现中文乱码写在MvcInitializer中依旧不是最前面的</p>
<p>我们可以写在SecurityInitializer中，这里应该是最前面了。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//解决中文传入Security乱码的问题</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">beforeSpringSecurityFilterChain</span><span class="hljs-params">(ServletContext servletContext)</span> &#123;<br>    servletContext.addFilter(<span class="hljs-string">&quot;characterEncodingFilter&quot;</span>,<span class="hljs-keyword">new</span> <span class="hljs-title class_">CharacterEncodingFilter</span>(<span class="hljs-string">&quot;UTF-8&quot;</span>,<span class="hljs-literal">true</span>))<br>            .addMappingForUrlPatterns(<span class="hljs-literal">null</span>,<span class="hljs-literal">false</span>,<span class="hljs-string">&quot;/*&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="分析人物模块"><a href="#分析人物模块" class="headerlink" title="分析人物模块"></a>分析人物模块</h4><p>管理员：书籍管理、借阅列表</p>
<p>同学：书籍借阅、自己的借阅列表</p>
<h4 id="前端页面修改"><a href="#前端页面修改" class="headerlink" title="前端页面修改"></a>前端页面修改</h4><h3 id="用户信息读取-传入Thymeleaf"><a href="#用户信息读取-传入Thymeleaf" class="headerlink" title="用户信息读取+传入Thymeleaf"></a>用户信息读取+传入Thymeleaf</h3><p>我们想在进入index界面的时候直接获取用户信息（包括用户名和用户身份）</p>
<p>在Controller进行用户信息读取有很多种方法。其中一种是利用SecurityContext，还有就是从Session获取信息。</p>
<p>我们在SecurityConfiguration登陆成功之后加了一部分操作。我们先从Session中获取用户信息，然后再通过重定向的方式进行主页的跳转。</p>
<h4 id="SecurityConfigutation"><a href="#SecurityConfigutation" class="headerlink" title="SecurityConfigutation"></a>SecurityConfigutation</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//获取用户信息</span><br><span class="hljs-meta">@Resource</span><br>UserMapper mapper;<br><br><span class="hljs-comment">//lambda表达式获取用户信息</span><br>http.successHandler(<span class="hljs-built_in">this</span>::onAuthenticationSuccess)<br><br><span class="hljs-comment">//获取用户信息</span><br><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onAuthenticationSuccess</span><span class="hljs-params">(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication)</span> <span class="hljs-keyword">throws</span> IOException, ServletException &#123;<br>    <span class="hljs-type">HttpSession</span> <span class="hljs-variable">session</span> <span class="hljs-operator">=</span> httpServletRequest.getSession();<br>    <span class="hljs-type">AuthUser</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> mapper.getPasswordByUsername(authentication.getName());<br>    session.setAttribute(<span class="hljs-string">&quot;user&quot;</span>,user);<br>    httpServletResponse.sendRedirect(<span class="hljs-string">&quot;/bookmanager/index&quot;</span>);<br>&#125;<br><br></code></pre></td></tr></table></figure>

<h4 id="PageController"><a href="#PageController" class="headerlink" title="PageController"></a>PageController</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/index&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">index</span><span class="hljs-params">(<span class="hljs-meta">@SessionAttribute(&quot;user&quot;)</span> AuthUser user , Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,user);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;index&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="前端传入值"><a href="#前端传入值" class="headerlink" title="前端传入值"></a>前端传入值</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;user.getName()&#125;&quot;</span>&gt;</span>John Brown<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;user.getRole().equals(&#x27;user&#x27;)?&#x27;普通学生&#x27; : &#x27;管理员&#x27;&#125;&quot;</span>&gt;</span>UI | UX Designer<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="不同权限显示不同页面"><a href="#不同权限显示不同页面" class="headerlink" title="不同权限显示不同页面"></a>不同权限显示不同页面</h2><p>我们制作一个主页，但是里面的内容划分根据不同的权限会有不同的消失效果，这就利用到了Security对Thymeleaf的支持。</p>
<h4 id="数据库输入信息"><a href="#数据库输入信息" class="headerlink" title="数据库输入信息"></a>数据库输入信息</h4><p>由于主页只能注册学生相关信息，所以管理员信息只能通过数据库进行输入。</p>
<p><img src="/image/22.07.26/image_4Qj1J4YqQb.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="Security赋予管理员登陆权限"><a href="#Security赋予管理员登陆权限" class="headerlink" title="Security赋予管理员登陆权限"></a>Security赋予管理员登陆权限</h4><p>我们将<code>hasRole()</code>改成<code>hasAnyRole()</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">.anyRequest().hasAnyRole(<span class="hljs-string">&quot;user&quot;</span>,<span class="hljs-string">&quot;admin&quot;</span>)     <span class="hljs-comment">//所有请求必须登陆并且是user角色才可以访问（不包含上面的静态资源）</span><br></code></pre></td></tr></table></figure>

<h3 id="菜单栏"><a href="#菜单栏" class="headerlink" title="菜单栏"></a>菜单栏</h3><p>菜单栏我们并不会进行两个页面的书写，但是我们会不同的显示进行不同的划分。</p>
<h4 id="管理员"><a href="#管理员" class="headerlink" title="管理员"></a>管理员</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!--图书管理员菜单--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">sec:authorize</span>=<span class="hljs-string">&quot;hasRole(&#x27;admin&#x27;)&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;all-product.html&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;icon-menu feather-icon&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://www.w3.org/2000/svg&quot;</span> <span class="hljs-attr">viewbox</span>=<span class="hljs-string">&quot;0 0 24 24&quot;</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">&quot;none&quot;</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">&quot;currentColor&quot;</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">&quot;2&quot;</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;feather feather-home&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">&quot;M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">polyline</span> <span class="hljs-attr">points</span>=<span class="hljs-string">&quot;9 22 9 12 15 12 15 22&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">polyline</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;menu-text&quot;</span>&gt;</span><br>            借阅信息<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">sec:authorize</span>=<span class="hljs-string">&quot;hasRole(&#x27;admin&#x27;)&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;orders.html&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;icon-menu feather-icon&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://www.w3.org/2000/svg&quot;</span> <span class="hljs-attr">viewbox</span>=<span class="hljs-string">&quot;0 0 24 24&quot;</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">&quot;none&quot;</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">&quot;currentColor&quot;</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">&quot;2&quot;</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;feather feather-truck&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">rect</span> <span class="hljs-attr">x</span>=<span class="hljs-string">&quot;1&quot;</span> <span class="hljs-attr">y</span>=<span class="hljs-string">&quot;3&quot;</span> <span class="hljs-attr">width</span>=<span class="hljs-string">&quot;15&quot;</span> <span class="hljs-attr">height</span>=<span class="hljs-string">&quot;13&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">rect</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">polygon</span> <span class="hljs-attr">points</span>=<span class="hljs-string">&quot;16 8 20 8 23 11 23 16 16 16 16 8&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">polygon</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">&quot;5.5&quot;</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">&quot;18.5&quot;</span> <span class="hljs-attr">r</span>=<span class="hljs-string">&quot;2.5&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">circle</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">&quot;18.5&quot;</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">&quot;18.5&quot;</span> <span class="hljs-attr">r</span>=<span class="hljs-string">&quot;2.5&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">circle</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;menu-text&quot;</span>&gt;</span><br>            图书管理<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h4 id="学生菜单"><a href="#学生菜单" class="headerlink" title="学生菜单"></a>学生菜单</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!--学生菜单--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">sec:authorize</span>=<span class="hljs-string">&quot;hasRole(&#x27;user&#x27;)&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;all-product.html&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;icon-menu feather-icon&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://www.w3.org/2000/svg&quot;</span> <span class="hljs-attr">viewbox</span>=<span class="hljs-string">&quot;0 0 24 24&quot;</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">&quot;none&quot;</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">&quot;currentColor&quot;</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">&quot;2&quot;</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;feather feather-home&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">&quot;M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">polyline</span> <span class="hljs-attr">points</span>=<span class="hljs-string">&quot;9 22 9 12 15 12 15 22&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">polyline</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;menu-text&quot;</span>&gt;</span><br>            本人借阅信息<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">sec:authorize</span>=<span class="hljs-string">&quot;hasRole(&#x27;user&#x27;)&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;orders.html&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;icon-menu feather-icon&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://www.w3.org/2000/svg&quot;</span> <span class="hljs-attr">viewbox</span>=<span class="hljs-string">&quot;0 0 24 24&quot;</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">&quot;none&quot;</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">&quot;currentColor&quot;</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">&quot;2&quot;</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">&quot;round&quot;</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;feather feather-truck&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">rect</span> <span class="hljs-attr">x</span>=<span class="hljs-string">&quot;1&quot;</span> <span class="hljs-attr">y</span>=<span class="hljs-string">&quot;3&quot;</span> <span class="hljs-attr">width</span>=<span class="hljs-string">&quot;15&quot;</span> <span class="hljs-attr">height</span>=<span class="hljs-string">&quot;13&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">rect</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">polygon</span> <span class="hljs-attr">points</span>=<span class="hljs-string">&quot;16 8 20 8 23 11 23 16 16 16 16 8&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">polygon</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">&quot;5.5&quot;</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">&quot;18.5&quot;</span> <span class="hljs-attr">r</span>=<span class="hljs-string">&quot;2.5&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">circle</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">&quot;18.5&quot;</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">&quot;18.5&quot;</span> <span class="hljs-attr">r</span>=<span class="hljs-string">&quot;2.5&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">circle</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;menu-text&quot;</span>&gt;</span><br>            图书借阅<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="想要每次进入都直接访问主页"><a href="#想要每次进入都直接访问主页" class="headerlink" title="想要每次进入都直接访问主页"></a>想要每次进入都直接访问主页</h2><p>思路一：让其登陆直接进入主页，先去session找，再去数据库找(找到了给session）,如果都没有，就给你送回登陆页面。</p>
<p>思路二：登陆直接进入登陆页面，如果找到了登录信息（先session后数据库）那么给你送到主页。（本项目不回写思路二，因为在两个地方进行判断没有必要并且容易出现多次重定向）</p>
<p>①采用数据库保存Token的方法</p>
<p>②如果直接访问主页，如果访问主页没有权限，那么从数据库中寻找权限，否则跳转回登陆页面。</p>
<p>③如果直接访问登陆页面，且有 登录信息，那么直接跳转到主页。</p>
<h4 id="设置数据库形式的记住我"><a href="#设置数据库形式的记住我" class="headerlink" title="设置数据库形式的记住我"></a>设置数据库形式的记住我</h4><p><em><strong>SecurityConfiguration</strong></em></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Resource</span><br>PersistentTokenRepository repository;<br><br><span class="hljs-meta">@Bean</span><br><span class="hljs-keyword">public</span> PersistentTokenRepository <span class="hljs-title function_">jdbcRepository</span><span class="hljs-params">(<span class="hljs-meta">@Autowired</span> DataSource dataSource)</span>&#123;<br>    <span class="hljs-type">JdbcTokenRepositoryImpl</span> <span class="hljs-variable">repository</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">JdbcTokenRepositoryImpl</span>();  <span class="hljs-comment">//使用基于JDBC的实现</span><br>    repository.setDataSource(dataSource);   <span class="hljs-comment">//配置数据源</span><br>    repository.setCreateTableOnStartup(<span class="hljs-literal">true</span>);   <span class="hljs-comment">//启动时自动创建用于存储Token的表（建议第一次启动之后删除该行）</span><br>    <span class="hljs-keyword">return</span> repository;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java">.and()<br>.rememberMe()<br>.rememberMeParameter(<span class="hljs-string">&quot;remember&quot;</span>)<br>.tokenRepository(repository)<br>.tokenValiditySeconds(<span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">24</span> * <span class="hljs-number">7</span>)  <span class="hljs-comment">//Token的有效时间（秒）默认为14天</span><br></code></pre></td></tr></table></figure>

<p>出现了报错：</p>
<p>因为我们的记住我是在跳转index之前对Cookie进行了一个user值的存入。我们现在直接进入index，因为没有user的权限，所以被拦下来了。</p>
<h4 id="配置index的Controller"><a href="#配置index的Controller" class="headerlink" title="配置index的Controller"></a>配置index的Controller</h4><p>我们对用户携带的Cookie进行了判断。</p>
<p>如果有user这个Session那么我们直接把他进行一个model设置。</p>
<p>如果没有，我们将获取被记住的登陆者的名字，通过名字查找用户的信息，将其封装在一个user对象中。然后对其进行session设置，最后再进行model设置。</p>
<p>model是给前端的user变量传值，方便进行身份判断。在此做出区别，model传给的是前端的参数，session传给的是Cookie中的信息。并不相等，但无论如何model都是要进行传值的，session可以进行传递，但是model只有在当前的controller才能进行赋值。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Resource</span><br>UserMapper mapper;<br><br><span class="hljs-meta">@RequestMapping(&quot;/index&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">index</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    <span class="hljs-type">AuthUser</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> (AuthUser) session.getAttribute(<span class="hljs-string">&quot;user&quot;</span>);<br>    <span class="hljs-keyword">if</span>(user == <span class="hljs-literal">null</span>)&#123;<br>        <span class="hljs-type">Authentication</span> <span class="hljs-variable">authentication</span> <span class="hljs-operator">=</span> SecurityContextHolder.getContext().getAuthentication();<br>        user = mapper.getPasswordByUsername(authentication.getName());<br>        session.setAttribute(<span class="hljs-string">&quot;user&quot;</span>,user);<br>    &#125;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,user);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;index&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="页面内容和划分"><a href="#页面内容和划分" class="headerlink" title="页面内容和划分"></a>页面内容和划分</h1><p>&amp;#x20; 已知管理员有两个页面（所有的借阅信息，增删改书籍），学生有两个界面（显示自己的借阅信息，借书还书）。</p>
<p>为了节省代码量，并且也没有必要将所有的信息进行展示然后再进行权限控制，我们决定设置一个头部模板，将前面相关的，相似的页面进行套用。</p>
<h3 id="页面位置分配"><a href="#页面位置分配" class="headerlink" title="页面位置分配"></a>页面位置分配</h3><h4 id="页面模板"><a href="#页面模板" class="headerlink" title="页面模板"></a>页面模板</h4><p>侧边栏和用户名放到template模板中</p>
<p>给其中的模板进行命名备注<code>th:fragment</code>。</p>
<p><img src="/image/22.07.26/image_Kfv48rgeIq.png" srcset="/img/loading.gif" lazyload></p>
<p>引用部分：</p>
<p><img src="/image/22.07.26/image_Ih7viWkpVA.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="页面重组"><a href="#页面重组" class="headerlink" title="页面重组"></a>页面重组</h4><p>我们对整个项目的页面进行结构重组。在页面中给页面分成admin和user两部分。在controller中将页面分成api和page两部分。方便页面进行访问，也方便Security进行控制划分。</p>
<p>注意：修改了Controller的前缀之后一定要在SecurityConfiguration中对路径进行修改。</p>
<p><img src="/image/22.07.26/image_1QGBnroC7J.png" srcset="/img/loading.gif" lazyload></p>
<p><img src="/image/22.07.26/image_Ku721e1qeS.png" srcset="/img/loading.gif" lazyload></p>
<p><img src="/image/22.07.26/image_yi6akLGasb.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="修改SecurityConfiguration相关地址"><a href="#修改SecurityConfiguration相关地址" class="headerlink" title="修改SecurityConfiguration相关地址"></a>修改SecurityConfiguration相关地址</h4><p>我们给Controller加过前缀之后，必须要给Security配置了的地址转向进行配置。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//拦截放行</span><br>.authorizeRequests()   <span class="hljs-comment">//首先需要配置哪些请求会被拦截，哪些请求必须具有什么角色才能访问</span><br>.antMatchers(<span class="hljs-string">&quot;/static/**&quot;</span>,<span class="hljs-string">&quot;/page/auth/**&quot;</span>,<span class="hljs-string">&quot;/api/auth/**&quot;</span>).permitAll()    <span class="hljs-comment">//静态资源，使用permitAll来运行任何人访问（注意一定要放在前面）</span><br>.antMatchers(<span class="hljs-string">&quot;/page/user/**&quot;</span>).hasRole(<span class="hljs-string">&quot;user&quot;</span>)<br>.antMatchers(<span class="hljs-string">&quot;/page/admin/**&quot;</span>).hasRole(<span class="hljs-string">&quot;admin&quot;</span>)<br>.anyRequest().hasAnyRole(<span class="hljs-string">&quot;user&quot;</span>,<span class="hljs-string">&quot;admin&quot;</span>)     <span class="hljs-comment">//所有请求必须登陆并且是user角色才可以访问（不包含上面的静态资源）</span><br><br><span class="hljs-comment">//自定义登陆页面</span><br>.and()<br>.formLogin()       <span class="hljs-comment">//配置Form表单登陆</span><br>.loginPage(<span class="hljs-string">&quot;/page/auth/login&quot;</span>)       <span class="hljs-comment">//登陆页面地址（GET）</span><br>.loginProcessingUrl(<span class="hljs-string">&quot;/api/auth/login&quot;</span>)    <span class="hljs-comment">//form表单提交地址（POST）</span><br><span class="hljs-comment">//lambda表达式获取用户信息</span><br>.successHandler(<span class="hljs-built_in">this</span>::onAuthenticationSuccess)<br>.permitAll()    <span class="hljs-comment">//登陆页面也需要允许所有人访问</span><br><br><span class="hljs-comment">//退出</span><br>.and()<br>.logout()<br>.logoutUrl(<span class="hljs-string">&quot;/api/auth/logout&quot;</span>)    <span class="hljs-comment">//退出登陆的请求地址</span><br>.logoutSuccessUrl(<span class="hljs-string">&quot;/page/auth/login&quot;</span>)    <span class="hljs-comment">//退出后重定向的地址</span><br></code></pre></td></tr></table></figure>

<h4 id="静态文件调整"><a href="#静态文件调整" class="headerlink" title="静态文件调整"></a>静态文件调整</h4><p>单独对文件夹外面的静态资源的地址进行配置</p>
<p><em><strong>thymeleaf链接地址</strong></em>要加斜杠表示的是WEB-INF根目录,如果不加斜杠表示的就是当前目录。</p>
<p>本项目的一大工程就是将原文的链接换成thymeleaf版本的链接</p>
<p>包括html文件夹中的资源地址</p>
<p><img src="/image/22.07.26/image_hfZIEGY5m4.png" srcset="/img/loading.gif" lazyload></p>
<p>MvcConfiguration</p>
<p>静态文件并不需要多做任何改变。</p>
<h4 id="重定向index分类工作"><a href="#重定向index分类工作" class="headerlink" title="重定向index分类工作"></a>重定向index分类工作</h4><h4 id="登录POST请求报错"><a href="#登录POST请求报错" class="headerlink" title="登录POST请求报错"></a>登录POST请求报错</h4><p>原来的请求登录doLogin请求换成Thymeleaf样式的连接并且加上斜杠。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">method</span>=<span class="hljs-string">&quot;post&quot;</span> <span class="hljs-attr">th:action</span>=<span class="hljs-string">&quot;@&#123;/api/auth/login&#125;&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="页面搭建"><a href="#页面搭建" class="headerlink" title="页面搭建"></a>页面搭建</h3><h4 id="Controller权限"><a href="#Controller权限" class="headerlink" title="Controller权限"></a>Controller权限</h4><p>我象征的东拼西凑了一下网页，结果发现点book按钮的时候，不能进去（网页一片白）？</p>
<p>结果发现是没有获取用户信息，所以给我拦住了所以我们新对Controller进行修改.</p>
<p>我们在写Controller的时候设置了两个参数，一个是Session，session让我们通过Security，model是为了向前端传入数值。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/book&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">book</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,service.findUser(session));<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;/admin/book&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="–管理员图书管理"><a href="#–管理员图书管理" class="headerlink" title="–管理员图书管理"></a>–管理员图书管理</h1><h2 id="思路-1"><a href="#思路-1" class="headerlink" title="思路"></a>思路</h2><p>首先将前端页面配置好。再实现网页进入（包括点击侧边栏的Thymeleaf链接和Controller中的身份认证页面跳转）</p>
<p><img src="/image/22.07.26/image_YqIbYEI-EE.png" srcset="/img/loading.gif" lazyload></p>
<h3 id="页面上"><a href="#页面上" class="headerlink" title="页面上"></a>页面上</h3><p>可以设置图书展示和图书删除在一个页面，增加图书再另一个界面。</p>
<h3 id="Controller-2"><a href="#Controller-2" class="headerlink" title="Controller"></a>Controller</h3><p>我们将展示放在admin页面controller中，将添加删除放在admin api controller中，将页面和操作明确区分开来。</p>
<h2 id="查询图书列表"><a href="#查询图书列表" class="headerlink" title="查询图书列表"></a>查询图书列表</h2><p>思路就是先写前端对应的输出位置，然后从后端实体类→mapper→service→Controller→前端</p>
<h4 id="Book实体类"><a href="#Book实体类" class="headerlink" title="Book实体类"></a>Book实体类</h4><p>想要查询书籍列表我们首先要有实体类依托</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Book</span> &#123;<br>    <span class="hljs-type">int</span> id;<br>    String title;<br>    String desc;<br>    <span class="hljs-type">double</span> price;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="BookMapper"><a href="#BookMapper" class="headerlink" title="BookMapper"></a>BookMapper</h4><p>有了实体类我们可以通过List&lt;实体类&gt;进行查询图书列表合集</p>
<p>要打上<code>@Mapper</code>注释</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Mapper</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">BookMapper</span> &#123;<br>    <span class="hljs-meta">@Select(&quot;select * from book&quot;)</span><br>    List&lt;Book&gt; <span class="hljs-title function_">allBook</span><span class="hljs-params">()</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="BookService"><a href="#BookService" class="headerlink" title="BookService"></a>BookService</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">BookService</span> &#123;<br>    List&lt;Book&gt; <span class="hljs-title function_">getAllBook</span><span class="hljs-params">()</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="BookServiceImpl"><a href="#BookServiceImpl" class="headerlink" title="BookServiceImpl"></a>BookServiceImpl</h4><p>我们将mapper查到的东西原封不动的返回到Controller</p>
<p>Service调用mapper的方法</p>
<p>使用<code>@Service</code>注解</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Service</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">BookServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">BookService</span> &#123;<br><br>    <span class="hljs-meta">@Resource</span><br>    BookMapper mapper;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> List&lt;Book&gt; <span class="hljs-title function_">getAllBook</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> mapper.allBook();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="AdminPageController"><a href="#AdminPageController" class="headerlink" title="AdminPageController"></a>AdminPageController</h4><p>Controller调用Service方法</p>
<p>我们通过model变量将查到的列表再一并传给前端页面，我们的目的是直接让Thymeleaf模板进行解析。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Resource</span><br>BookService bookService;<br><br><span class="hljs-meta">@RequestMapping(&quot;/book&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">book</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,service.findUser(session));<br>    model.addAttribute(<span class="hljs-string">&quot;bookList&quot;</span>, bookService.getAllBook());<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;/admin/book&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="book-html"><a href="#book-html" class="headerlink" title="book.html"></a>book.html</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!--源代码--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">th:each</span>=<span class="hljs-string">&quot;abook : $&#123;bookList&#125;&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;#&#x27;+$&#123;abook.getId()&#125;&quot;</span>&gt;</span>#JH2033<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;《&#x27;+$&#123;abook.getTitle()&#125;+&#x27;》&#x27;&quot;</span>&gt;</span>#JH2033<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;abook.getDesc()&#125;&quot;</span>&gt;</span>22/06/2021<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;￥&#x27;+$&#123;abook.getPrice()&#125;&quot;</span>&gt;</span>$600<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;relative&quot;</span>&gt;</span><br><span class="hljs-comment">&lt;!--删除书籍--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;action-btn&quot;</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;&quot;</span>&gt;</span> <span class="hljs-comment">&lt;!--th:href=&quot;&#x27;delete-book?bid=&#x27;+$&#123;book.getBid()&#125;&quot;&gt;--&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;default-size &quot;</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">&quot;0 0 341.333 341.333 &quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">g</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">g</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">g</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">&quot;M170.667,85.333c23.573,0,42.667-19.093,42.667-42.667C213.333,19.093,194.24,0,170.667,0S128,19.093,128,42.667 C128,66.24,147.093,85.333,170.667,85.333z &quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">&quot;M170.667,128C147.093,128,128,147.093,128,170.667s19.093,42.667,42.667,42.667s42.667-19.093,42.667-42.667 S194.24,128,170.667,128z &quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">&quot;M170.667,256C147.093,256,128,275.093,128,298.667c0,23.573,19.093,42.667,42.667,42.667s42.667-19.093,42.667-42.667 C213.333,275.093,194.24,256,170.667,256z &quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">g</span>&gt;</span><br><br></code></pre></td></tr></table></figure>

<p><img src="/image/22.07.26/image_fyFy3Rit4X.png" srcset="/img/loading.gif" lazyload></p>
<p><img src="/image/22.07.26/image_a0sUQexnbG.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="怎么书籍id都是0-呢"><a href="#怎么书籍id都是0-呢" class="headerlink" title="怎么书籍id都是0 呢"></a>怎么书籍id都是0 呢</h4><p>是没有映射好，我们数据库中的字段是bid，我们应该给<strong>实体类中的字段和前端页面改成bid</strong>，这样就可以了。中间不用改，因为中间没涉及到具体的参数。</p>
<h2 id="删除图书"><a href="#删除图书" class="headerlink" title="删除图书"></a>删除图书</h2><h4 id="BookMapper-1"><a href="#BookMapper-1" class="headerlink" title="BookMapper"></a>BookMapper</h4><p>我们知道删除的依据是id</p>
<p>我们先在mapper中进行通过id删除书籍的操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Delete(&quot;delete from book where bid = #&#123;bid&#125;&quot;)</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">deleteBook</span><span class="hljs-params">(<span class="hljs-type">int</span> bid)</span>;<br></code></pre></td></tr></table></figure>

<h4 id="BookService-1"><a href="#BookService-1" class="headerlink" title="BookService"></a>BookService</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">BookService</span> &#123;<br>    List&lt;Book&gt; <span class="hljs-title function_">getAllBook</span><span class="hljs-params">()</span>;<br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">deleteBook</span><span class="hljs-params">(<span class="hljs-type">int</span> bid)</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="BookServiceImpl-1"><a href="#BookServiceImpl-1" class="headerlink" title="BookServiceImpl"></a>BookServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">deleteBook</span><span class="hljs-params">(<span class="hljs-type">int</span> bid)</span> &#123;<br>    mapper.deleteBook(bid);<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Controller-3"><a href="#Controller-3" class="headerlink" title="Controller"></a>Controller</h4><p>Controller部分我们进行详细的划分，将删除操作划分到api&#x2F;admin中，将展示和操作划分成两个部分</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Controller</span><br><span class="hljs-meta">@RequestMapping(&quot;/api/admin&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AdminApiController</span> &#123;<br><br>    <span class="hljs-meta">@Resource</span><br>    BookService service;<br><br>    <span class="hljs-meta">@RequestMapping(value = &quot;/del-book&quot;,method = RequestMethod.GET)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">deleteBook</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;id&quot;)</span> <span class="hljs-type">int</span> id)</span>&#123;<br>        service.deleteBook(id);<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;redirect:/page/admin/book&quot;</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Security权限配置"><a href="#Security权限配置" class="headerlink" title="Security权限配置"></a>Security权限配置</h4><p>将api&#x2F;admin的权限分配给admin</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">.antMatchers(<span class="hljs-string">&quot;/page/user/**&quot;</span>,<span class="hljs-string">&quot;/api/user/**&quot;</span>).hasRole(<span class="hljs-string">&quot;user&quot;</span>)<br>.antMatchers(<span class="hljs-string">&quot;/page/admin/**&quot;</span>,<span class="hljs-string">&quot;/api/admin/**&quot;</span>).hasRole(<span class="hljs-string">&quot;admin&quot;</span>)<br></code></pre></td></tr></table></figure>

<h4 id="触发器配置"><a href="#触发器配置" class="headerlink" title="触发器配置"></a>触发器配置</h4><p>删除书之前，删除借阅信息</p>
<p>所以：触发器设置给book表，在删除操作之前从borrow中删除bid&#x3D;old.bid</p>
<p><img src="/image/22.07.26/image_T-939rAeUQ.png" srcset="/img/loading.gif" lazyload></p>
<h4 id="book-html-1"><a href="#book-html-1" class="headerlink" title="book.html"></a>book.html</h4><p>路径极其容易出错。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;action-btn&quot;</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">&quot;@&#123;/api/admin/del-book?id=&#125;+$&#123;abook.getBid()&#125;&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="增加图书"><a href="#增加图书" class="headerlink" title="增加图书"></a>增加图书</h2><h3 id="按钮进入页面page"><a href="#按钮进入页面page" class="headerlink" title="按钮进入页面page"></a>按钮进入页面page</h3><h4 id="前端按钮"><a href="#前端按钮" class="headerlink" title="前端按钮"></a>前端按钮</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-btn&quot;</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">&quot;@&#123;/page/admin/add-book&#125;&quot;</span>&gt;</span>添加图书<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h4 id="AdminPageController-1"><a href="#AdminPageController-1" class="headerlink" title="AdminPageController"></a>AdminPageController</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(value = &quot;/add-book&quot;,method = RequestMethod.GET)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">addBook</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,service.findUser(session));<br>    model.addAttribute(<span class="hljs-string">&quot;bookList&quot;</span>, bookService.getAllBook());<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;/admin/add-book&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="报错"><a href="#报错" class="headerlink" title="报错"></a>报错</h4><p>我象征的东拼西凑了一下网页，结果发现点book按钮的时候，不能进去（网页一片白）？</p>
<p>结果发现是没有获取用户信息，所以给我拦住了所以我们新对Controller进行修改.</p>
<p>我们在写Controller的时候设置了两个参数，一个是Session，session让我们通过Security，model是为了向前端传入数值。</p>
<h3 id="添加图书api"><a href="#添加图书api" class="headerlink" title="添加图书api"></a>添加图书api</h3><h4 id="简单写一下Controller"><a href="#简单写一下Controller" class="headerlink" title="简单写一下Controller"></a>简单写一下Controller</h4><p>简单写一下add-book的apiController，将前端的数值传入Controller</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(value = &quot;/add-book&quot;,method = RequestMethod.POST)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">addBook</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;title&quot;)</span> String title,</span><br><span class="hljs-params">                      <span class="hljs-meta">@RequestParam(&quot;desc&quot;)</span> String desc,</span><br><span class="hljs-params">                      <span class="hljs-meta">@RequestParam(&quot;price&quot;)</span> String price)</span>&#123;<br>    <br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;redirect:/page/admin/add-book&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="BookMapper-2"><a href="#BookMapper-2" class="headerlink" title="BookMapper"></a>BookMapper</h4><p>desc是关键字，所以我们要加上飘</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Insert(&quot;insert into book(title,`desc`,price) values(#&#123;title&#125;,#&#123;desc&#125;,#&#123;price&#125;)&quot;)</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">addBook</span><span class="hljs-params">(<span class="hljs-meta">@Param(&quot;title&quot;)</span> String title, <span class="hljs-meta">@Param(&quot;desc&quot;)</span> String desc,<span class="hljs-meta">@Param(&quot;price&quot;)</span> <span class="hljs-type">double</span> price)</span>;<br><br></code></pre></td></tr></table></figure>

<h4 id="BookService-2"><a href="#BookService-2" class="headerlink" title="BookService"></a>BookService</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">void</span> <span class="hljs-title function_">addBook</span><span class="hljs-params">(String title,String desc,<span class="hljs-type">double</span> price)</span>;<br></code></pre></td></tr></table></figure>

<h4 id="BookServiceImpl-2"><a href="#BookServiceImpl-2" class="headerlink" title="BookServiceImpl"></a>BookServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">addBook</span><span class="hljs-params">(String title, String desc, <span class="hljs-type">double</span> price)</span> &#123;<br>    mapper.addBook(title,desc,price);<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Controller-4"><a href="#Controller-4" class="headerlink" title="Controller"></a>Controller</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(value = &quot;/add-book&quot;,method = RequestMethod.POST)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">addBook</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;title&quot;)</span> String title,</span><br><span class="hljs-params">                      <span class="hljs-meta">@RequestParam(&quot;desc&quot;)</span> String desc,</span><br><span class="hljs-params">                      <span class="hljs-meta">@RequestParam(&quot;price&quot;)</span> <span class="hljs-type">double</span> price)</span>&#123;<br>    service.addBook(title,desc,price);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;redirect:/page/admin/book&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="–学生借阅管理"><a href="#–学生借阅管理" class="headerlink" title="–学生借阅管理"></a>–学生借阅管理</h1><h2 id="显示在馆书籍list"><a href="#显示在馆书籍list" class="headerlink" title="显示在馆书籍list"></a>显示在馆书籍list</h2><h4 id="思路-2"><a href="#思路-2" class="headerlink" title="思路"></a>思路</h4><p>可以通过sql语句进行筛选，我们在这里选择的是通过Service进行筛选。</p>
<p>先通过bookmapper查到所有书籍，再通过borrowmapper查到所有的借阅信息。</p>
<p>怎么才能进行筛选呢？</p>
<p>我们在Service中利用实体类获取了所有的borrow的bid成了一个数字列表。</p>
<p>再将books中bid再数字列表中的book对象删掉。</p>
<h4 id="Mapper-1"><a href="#Mapper-1" class="headerlink" title="Mapper"></a>Mapper</h4><p>bookmapper</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Select(&quot;select * from book&quot;)</span><br>List&lt;Book&gt; <span class="hljs-title function_">allBook</span><span class="hljs-params">()</span>;<br></code></pre></td></tr></table></figure>

<p>borrowmapper</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Select(&quot;select * from borrow&quot;)</span><br>List&lt;Borrow&gt; <span class="hljs-title function_">borrowList</span><span class="hljs-params">()</span>;<br></code></pre></td></tr></table></figure>

<h4 id="Service"><a href="#Service" class="headerlink" title="Service"></a>Service</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//获取全部书籍信息</span><br>List&lt;Book&gt; <span class="hljs-title function_">getAllBook</span><span class="hljs-params">()</span>;<br><br><span class="hljs-comment">//获取在馆书籍</span><br><span class="hljs-keyword">public</span> List&lt;Book&gt; <span class="hljs-title function_">getAllBookWithoutBorrow</span><span class="hljs-params">()</span>;<br></code></pre></td></tr></table></figure>

<h4 id="ServiceImpl"><a href="#ServiceImpl" class="headerlink" title="ServiceImpl"></a>ServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Resource</span><br>BookMapper mapper;<br><span class="hljs-meta">@Resource</span><br>BorrowMapper borrowmapper;<br><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> List&lt;Book&gt; <span class="hljs-title function_">getAllBook</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-keyword">return</span> mapper.allBook();<br>&#125;<br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> List&lt;Book&gt; <span class="hljs-title function_">getAllBookWithoutBorrow</span><span class="hljs-params">()</span> &#123;<br>    List&lt;Book&gt; books = mapper.allBook();<br>    List&lt;Integer&gt; borrows = borrowmapper.borrowList()<br>            .stream()<br>            .map(Borrow::getBid)<br>            .collect(Collectors.toList());<br>    <span class="hljs-keyword">return</span> books<br>            .stream()<br>            .filter(book -&gt; !borrows.contains(book.getBid()))<br>            .collect(Collectors.toList());<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Controller-5"><a href="#Controller-5" class="headerlink" title="Controller"></a>Controller</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/index&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">index</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,service.findUser(session));<br>    model.addAttribute(<span class="hljs-string">&quot;bookList&quot;</span>, bookService.getAllBookWithoutBorrow());<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;/user/index&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="前端页面"><a href="#前端页面" class="headerlink" title="前端页面"></a>前端页面</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">th:each</span>=<span class="hljs-string">&quot;bbook:$&#123;bookList&#125;&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;#&#x27;+$&#123;bbook.getBid()&#125;&quot;</span>&gt;</span>书籍id<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;《&#x27;+$&#123;bbook.getTitle()&#125;+&#x27;》&#x27;&quot;</span>&gt;</span>可借书籍<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;bbook.getDesc()&#125;&quot;</span>&gt;</span>书籍描述<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;bbook.getPrice()&#125;&quot;</span>&gt;</span>书籍价格<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="图书借阅api-amp-x20"><a href="#图书借阅api-amp-x20" class="headerlink" title="图书借阅api&amp;#x20;"></a>图书借阅api&amp;#x20;</h2><h4 id="思路-3"><a href="#思路-3" class="headerlink" title="思路"></a>思路</h4><p>我们的本意其实只是想输入sid和bid直接进行添加，可是虽然bid我们能获取到，但是sid我们并不能从页面中直接获取。（但是我们可以获得uid）</p>
<p>我们之前在student表中通过uid查找到sid，把sid传到service，由service调用mapper的添加操作。</p>
<h4 id="Mapper-2"><a href="#Mapper-2" class="headerlink" title="Mapper"></a>Mapper</h4><p>borrowmapper</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Insert(&quot;insert into borrow(bid,sid,`time`) values(#&#123;bid&#125;,#&#123;sid&#125;,NOW())&quot;)</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">addBorrow</span><span class="hljs-params">(<span class="hljs-meta">@Param(&quot;bid&quot;)</span> <span class="hljs-type">int</span> bid,<span class="hljs-meta">@Param(&quot;sid&quot;)</span> <span class="hljs-type">int</span> sid)</span>;<br></code></pre></td></tr></table></figure>

<p>usermapper</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Select(&quot;select sid from student where uid = #&#123;uid&#125;&quot;)</span><br>Integer <span class="hljs-title function_">getSidByUserId</span><span class="hljs-params">(<span class="hljs-type">int</span> uid)</span>;<br><br></code></pre></td></tr></table></figure>

<h4 id="Service-1"><a href="#Service-1" class="headerlink" title="Service"></a>Service</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//借书</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">borrowBook</span><span class="hljs-params">(<span class="hljs-type">int</span> bid,<span class="hljs-type">int</span> sid)</span>;<br></code></pre></td></tr></table></figure>

<h4 id="ServiceImpl-1"><a href="#ServiceImpl-1" class="headerlink" title="ServiceImpl"></a>ServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Resource</span><br>BorrowMapper mapper;<br><span class="hljs-meta">@Resource</span><br>UserMapper usermapper;<br><span class="hljs-comment">//借书</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">borrowBook</span><span class="hljs-params">(<span class="hljs-type">int</span> bid,<span class="hljs-type">int</span> id)</span> &#123;<br>    <span class="hljs-type">Integer</span> <span class="hljs-variable">sid</span> <span class="hljs-operator">=</span> usermapper.getSidByUserId(id);<br>    <span class="hljs-keyword">if</span>(sid==<span class="hljs-literal">null</span>)&#123;<span class="hljs-keyword">return</span>;&#125;<br>    mapper.addBorrow(bid,sid);<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Controller-6"><a href="#Controller-6" class="headerlink" title="Controller"></a>Controller</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Controller</span><br><span class="hljs-meta">@RequestMapping(&quot;/api/user&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserApiController</span> &#123;<br><br>    <span class="hljs-meta">@Resource</span><br>    BorrowService service;<br><br>    <span class="hljs-meta">@RequestMapping(&quot;/borrow-book&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">borrowBook</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;id&quot;)</span> <span class="hljs-type">int</span> bid,</span><br><span class="hljs-params">                             <span class="hljs-meta">@SessionAttribute(&quot;user&quot;)</span>AuthUser user)</span>&#123;<br>        service.borrowBook(bid, user.getId());<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;redirect:/page/user/book&quot;</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="前端页面-1"><a href="#前端页面-1" class="headerlink" title="前端页面"></a>前端页面</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;action-btn&quot;</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">&quot;@&#123;/api/user/borrow-book?id=&#125;+$&#123;bbook.getBid()&#125;&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h1 id="–借阅信息展示"><a href="#–借阅信息展示" class="headerlink" title="–借阅信息展示"></a>–借阅信息展示</h1><h3 id="所有借阅信息"><a href="#所有借阅信息" class="headerlink" title="所有借阅信息"></a>所有借阅信息</h3><h4 id="思路-4"><a href="#思路-4" class="headerlink" title="思路"></a>思路</h4><p>在查询所有书籍时逻辑较为简单，我们定义一个比较全面的borrow实体类，想要通过多表联查的方式将列表（List&lt;Borrow&gt;）直接查到并放到前端进行解析。在Controller层，除了让页面可以正常展示的user授权过程，另加了一个列表赋值的过程。</p>
<h4 id="Borrow实体类"><a href="#Borrow实体类" class="headerlink" title="Borrow实体类"></a>Borrow实体类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Borrow</span> &#123;<br>    <span class="hljs-type">int</span> id;<br><br>    <span class="hljs-type">int</span> bid;<br>    String title;<br>    String desc;<br>    <span class="hljs-type">double</span> price;<br><br>    <span class="hljs-type">int</span> sid;<br>    String name;<br>    String sex;<br>    String grade;<br><br>    Date time;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="BorrowMapper"><a href="#BorrowMapper" class="headerlink" title="BorrowMapper"></a>BorrowMapper</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//查看所有借阅信息</span><br><span class="hljs-meta">@Select(&quot;SELECT * FROM (SELECT * FROM borrow LEFT JOIN book USING (bid)) e LEFT JOIN student USING (sid)&quot;)</span><br>List&lt;Borrow&gt; <span class="hljs-title function_">allBorrowList</span><span class="hljs-params">()</span>;<br></code></pre></td></tr></table></figure>

<h4 id="Service-2"><a href="#Service-2" class="headerlink" title="Service"></a>Service</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//显示所有借阅信息</span><br>List&lt;Borrow&gt; <span class="hljs-title function_">allBorrowList</span><span class="hljs-params">()</span>;<br></code></pre></td></tr></table></figure>

<h4 id="ServiceImpl-2"><a href="#ServiceImpl-2" class="headerlink" title="ServiceImpl"></a>ServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//查看所有借阅信息</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> List&lt;Borrow&gt; <span class="hljs-title function_">allBorrowList</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-keyword">return</span> mapper.allBorrowList();<br>&#125;<br><br></code></pre></td></tr></table></figure>

<h4 id="Controller-7"><a href="#Controller-7" class="headerlink" title="Controller"></a>Controller</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/index&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">index</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,service.findUser(session));<br>    model.addAttribute(<span class="hljs-string">&quot;allBorrowList&quot;</span>,borrowservice.allBorrowList());<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;/admin/index&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="前端页面-2"><a href="#前端页面-2" class="headerlink" title="前端页面"></a>前端页面</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">th:each</span>=<span class="hljs-string">&quot;borrow:$&#123;allBorrowList&#125;&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;#&#x27;+$&#123;borrow.getId()&#125;&quot;</span>&gt;</span>借阅ID<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;《&#x27;+$&#123;borrow.getTitle()&#125;+&#x27;》&#x27;&quot;</span>&gt;</span>书籍名称<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;borrow.getName()&#125;&quot;</span>&gt;</span>借阅人<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;#&#x27;+$&#123;borrow.getSid()&#125;&quot;</span>&gt;</span>借阅人学号<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;borrow.getTime()&#125;&quot;</span>&gt;</span>借阅时间<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="学生借阅信息"><a href="#学生借阅信息" class="headerlink" title="学生借阅信息"></a>学生借阅信息</h3><h4 id="思路-5"><a href="#思路-5" class="headerlink" title="思路"></a>思路</h4><p>我们获得个人借阅信息后，可以通过多表联查的方式获取到当前学生的借阅列表，将列表传到service，再传到controller，controller直接传到Thymeleaf进行列表解析。</p>
<p>此过程比查询全部的列表就多在要将sid从前端传到mapepr中。可是我们没有什么直接的post请求，确实，但是我们发现我们可以从id入手。我们在Service中通过id查找sid，再在service中将sid放入查询所用的mapper中，这样就可以完美的查到了。</p>
<p>前端的id传到service，由service变成sid传给mapper，mapper查到的再返回给service，通过service返回给Controller，可见service在其中的重要作用。</p>
<h4 id="BorrowMapper-1"><a href="#BorrowMapper-1" class="headerlink" title="BorrowMapper"></a>BorrowMapper</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//查看个人借阅信息</span><br><span class="hljs-meta">@Select(&quot;SELECT * FROM (SELECT * FROM borrow LEFT JOIN book USING (bid)) e LEFT JOIN student USING (sid) WHERE sid = #&#123;sid&#125;&quot;)</span><br>List&lt;Borrow&gt; <span class="hljs-title function_">ownBorrowList</span><span class="hljs-params">(<span class="hljs-type">int</span> sid)</span>;<br></code></pre></td></tr></table></figure>

<h4 id="Service-3"><a href="#Service-3" class="headerlink" title="Service"></a>Service</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//显示个人借阅信息</span><br>List&lt;Borrow&gt; <span class="hljs-title function_">ownBorrowList</span><span class="hljs-params">(HttpSession session)</span>;<br></code></pre></td></tr></table></figure>

<h4 id="ServiceImpl-3"><a href="#ServiceImpl-3" class="headerlink" title="ServiceImpl"></a>ServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//显示个人借阅信息</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> List&lt;Borrow&gt; <span class="hljs-title function_">ownBorrowList</span><span class="hljs-params">(HttpSession session)</span> &#123;<br>    <span class="hljs-type">AuthUser</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> (AuthUser) session.getAttribute(<span class="hljs-string">&quot;user&quot;</span>);<br>    <span class="hljs-type">Integer</span> <span class="hljs-variable">sid</span> <span class="hljs-operator">=</span> usermapper.getSidByUserId(user.getId());<br>    <span class="hljs-keyword">return</span> mapper.ownBorrowList(sid);<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Controller-8"><a href="#Controller-8" class="headerlink" title="Controller"></a>Controller</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/book&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">book</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,service.findUser(session));<br>    model.addAttribute(<span class="hljs-string">&quot;borrowList&quot;</span>, borrowService.ownBorrowList(session));<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;/user/book&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="前端页面-3"><a href="#前端页面-3" class="headerlink" title="前端页面"></a>前端页面</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">th:each</span>=<span class="hljs-string">&quot;borrow:$&#123;borrowList&#125;&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;#&#x27;+$&#123;borrow.getBid()&#125;&quot;</span>&gt;</span>书籍ID<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;&#x27;《&#x27;+$&#123;borrow.getTitle()&#125;+&#x27;》&#x27;&quot;</span>&gt;</span>书籍名称<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;borrow.getDesc()&#125;&quot;</span>&gt;</span>简介<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;borrow.getPrice()&#125;&quot;</span>&gt;</span>价格<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;borrow.getTime()&#125;&quot;</span>&gt;</span>借阅时间<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h3 id="报错部分"><a href="#报错部分" class="headerlink" title="报错部分"></a>报错部分</h3><blockquote>
<p>mapper传多个值要有@Param</p>
</blockquote>
<blockquote>
<p>报错说del-borrow不可用</p>
<p><img src="/image/22.07.26/image_G59qvD8Xtl.png" srcset="/img/loading.gif" lazyload></p>
<p>解决：果然是前端页面和mapper网址相关部分写错了。borrow写成了borrpw</p>
</blockquote>
<blockquote>
<p>借阅时间不能正常显示问题</p>
<p>因为在实体类中将时间定义的是</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">Date date;<br></code></pre></td></tr></table></figure>

<p>前端<code>getDate()</code></p>
<p>正确应该定义成</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">Date time;<br></code></pre></td></tr></table></figure>

<p>前端<code>getTime()</code></p>
</blockquote>
<h1 id="项目优化"><a href="#项目优化" class="headerlink" title="项目优化"></a>项目优化</h1><h3 id="四小块"><a href="#四小块" class="headerlink" title="四小块"></a>四小块</h3><h4 id="思路-6"><a href="#思路-6" class="headerlink" title="思路"></a>思路</h4><p>我们创建了一个实体类，将数据存储在其中。在我们service中创建实体类对象在其中设置值。因为我们将这个对象返回到Controller，所以我们可以直接调用其中的属性进行前端解析。</p>
<h4 id="实体类"><a href="#实体类" class="headerlink" title="实体类"></a>实体类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ShowCount</span> &#123;<br>    <span class="hljs-type">int</span> bookCount;<br>    <span class="hljs-type">int</span> studentCount;<br>    <span class="hljs-type">int</span> borrowCount;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="ShowService"><a href="#ShowService" class="headerlink" title="ShowService"></a>ShowService</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">ShowService</span> &#123;<br>    ShowCount <span class="hljs-title function_">showCount</span><span class="hljs-params">()</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="ShowServiceImpl"><a href="#ShowServiceImpl" class="headerlink" title="ShowServiceImpl"></a>ShowServiceImpl</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Service</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ShowServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">ShowService</span> &#123;<br><br>    <span class="hljs-meta">@Resource</span><br>    BookMapper bookMapper;<br>    <span class="hljs-meta">@Resource</span><br>    BorrowMapper borrowMapper;<br>    <span class="hljs-meta">@Resource</span><br>    UserMapper userMapper;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> ShowCount <span class="hljs-title function_">showCount</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ShowCount</span>(userMapper.getStudentCount(),<br>                bookMapper.getBookCount(),<br>                borrowMapper.getBorrowCount());<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="Controller-9"><a href="#Controller-9" class="headerlink" title="Controller"></a>Controller</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/index&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">index</span><span class="hljs-params">(HttpSession session, Model model)</span>&#123;<br>    model.addAttribute(<span class="hljs-string">&quot;user&quot;</span>,service.findUser(session));<br>    model.addAttribute(<span class="hljs-string">&quot;allBorrowList&quot;</span>,borrowservice.allBorrowList());<br>    model.addAttribute(<span class="hljs-string">&quot;bookCounts&quot;</span>,showService.showCount());<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;/admin/index&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="html代码"><a href="#html代码" class="headerlink" title="html代码"></a>html代码</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">h5</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-title&quot;</span>&gt;</span>学生数量<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-card-title&quot;</span>  <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;bookCounts.studentCount&#125;&quot;</span>&gt;</span>66k<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">h5</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-title&quot;</span>&gt;</span>书籍数量<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-card-title&quot;</span>  <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;bookCounts.bookCount&#125;&quot;</span>&gt;</span>15k<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span> <br><span class="hljs-tag">&lt;<span class="hljs-name">h5</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-title&quot;</span>&gt;</span>借阅数量<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;ad-card-title&quot;</span>  <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;bookCounts.borrowCount&#125;&quot;</span>&gt;</span>420k<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>                                                                       <br></code></pre></td></tr></table></figure>
              
            </div>
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/%E5%BC%80%E5%8F%91/" class="category-chain-item">开发</a>
  
  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/Java/">#Java</a>
      
        <a href="/tags/%E5%AE%9E%E6%88%98/">#实战</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>基于SSM+Security的图书管理系统</div>
      <div>http://example.com/2022/07/26/BookManagerSSM/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>Wahoyu</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2022年7月26日</div>
        </div>
      
      
      <div class="license-meta-item">
        <div>许可协议</div>
        <div>
          
            
            
              <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
              <span class="hint--top hint--rounded" aria-label="BY - 署名">
                <i class="iconfont icon-by"></i>
              </span>
              </a>
            
          
        </div>
      </div>
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/08/30/%E6%97%A5%E5%BF%97%E8%BF%9B%E5%8C%96%EF%BC%9AAOP+%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0%E6%97%A5%E5%BF%97%E8%BE%93%E5%87%BA/" title="日志进化：AOP+自定义注解实现日志输出">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">日志进化：AOP+自定义注解实现日志输出</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/07/06/JavaWeb/" title="基于Java Web的图书管理系统">
                        <span class="hidden-mobile">基于Java Web的图书管理系统</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
  <article id="comments" lazyload>
    
  <div id="valine"></div>
  <script type="text/javascript">
    Fluid.utils.loadComments('#valine', function() {
      Fluid.utils.createScript('https://lib.baomitu.com/valine/1.4.16/Valine.min.js', function() {
        var options = Object.assign(
          {"appId":"7WuaJQGQGU5GFxMKMtDzWYVI-gzGzoHsz","appKey":"zdCzx5CuURztPQQoi8LuXSWv","path":"window.location.pathname","placeholder":"请留下您的想法...","avatar":"retro","meta":["nick","mail","link"],"requiredFields":[],"pageSize":10,"lang":"zh-CN","highlight":false,"recordIP":true,"serverURLs":"https://7wuajqgq.lc-cn-n1-shared.com","emojiCDN":null,"emojiMaps":null,"enableQQ":true},
          {
            el: "#valine",
            path: window.location.pathname
          }
        )
        new Valine(options);
        Fluid.utils.waitElementVisible('#valine .vcontent', () => {
          var imgSelector = '#valine .vcontent img:not(.vemoji)';
          Fluid.plugins.imageCaption(imgSelector);
          Fluid.plugins.fancyBox(imgSelector);
        })
      });
    });
  </script>
  <noscript>Please enable JavaScript to view the comments</noscript>


  </article>


          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  






    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <text>哆啦是个梦</text> <div style="font-size: 0.85rem"> <span id="timeDate">载入天数...</span> <span id="times">载入时分秒...</span> <script src="/js/duration.js"></script> </div> 
    </div>
  
  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  

  

  

  

  

  

  




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.0/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      headingSelector : CONFIG.toc.headingSelector || 'h1,h2,h3,h4,h5,h6',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      collapseDepth   : CONFIG.toc.collapseDepth || 0,
      scrollSmooth    : true,
      headingsOffset  : -boardTop
    });
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }
  });
</script>


  <script>
  (function() {
    var enableLang = CONFIG.code_language.enable && CONFIG.code_language.default;
    var enableCopy = CONFIG.copy_btn;
    if (!enableLang && !enableCopy) {
      return;
    }

    function getBgClass(ele) {
      return Fluid.utils.getBackgroundLightness(ele) >= 0 ? 'code-widget-light' : 'code-widget-dark';
    }

    var copyTmpl = '';
    copyTmpl += '<div class="code-widget">';
    copyTmpl += 'LANG';
    copyTmpl += '</div>';
    jQuery('.markdown-body pre').each(function() {
      var $pre = jQuery(this);
      if ($pre.find('code.mermaid').length > 0) {
        return;
      }
      if ($pre.find('span.line').length > 0) {
        return;
      }

      var lang = '';

      if (enableLang) {
        lang = CONFIG.code_language.default;
        if ($pre[0].children.length > 0 && $pre[0].children[0].classList.length >= 2 && $pre.children().hasClass('hljs')) {
          lang = $pre[0].children[0].classList[1];
        } else if ($pre[0].getAttribute('data-language')) {
          lang = $pre[0].getAttribute('data-language');
        } else if ($pre.parent().hasClass('sourceCode') && $pre[0].children.length > 0 && $pre[0].children[0].classList.length >= 2) {
          lang = $pre[0].children[0].classList[1];
          $pre.parent().addClass('code-wrapper');
        } else if ($pre.parent().hasClass('markdown-body') && $pre[0].classList.length === 0) {
          $pre.wrap('<div class="code-wrapper"></div>');
        }
        lang = lang.toUpperCase().replace('NONE', CONFIG.code_language.default);
      }
      $pre.append(copyTmpl.replace('LANG', lang).replace('code-widget">',
        getBgClass($pre[0]) + (enableCopy ? ' code-widget copy-btn" data-clipboard-snippet><i class="iconfont icon-copy"></i>' : ' code-widget">')));

      if (enableCopy) {
        Fluid.utils.createScript('https://lib.baomitu.com/clipboard.js/2.0.10/clipboard.min.js', function() {
          var clipboard = new window.ClipboardJS('.copy-btn', {
            target: function(trigger) {
              var nodes = trigger.parentNode.childNodes;
              for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].tagName === 'CODE') {
                  return nodes[i];
                }
              }
            }
          });
          clipboard.on('success', function(e) {
            e.clearSelection();
            e.trigger.innerHTML = e.trigger.innerHTML.replace('icon-copy', 'icon-success');
            setTimeout(function() {
              e.trigger.innerHTML = e.trigger.innerHTML.replace('icon-success', 'icon-copy');
            }, 2000);
          });
        });
      }
    });
  })();
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/js/local-search.js" ></script>

  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiantiao.js"></script>



<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
